Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorLin Jen-Shin <godfat@godfat.org>2017-06-28 10:53:12 +0300
committerLin Jen-Shin <godfat@godfat.org>2017-06-28 10:53:12 +0300
commit35674fcd4732681286224c1c5fc92386ff53db7f (patch)
tree31585e8a89ebbf384bf9a9a61e9813331df8cdf7 /doc
parent07365e518330289149dd2135424c49fad19f401d (diff)
parent08ad0af49c017d740b43588c0809b3811d25a448 (diff)
Merge remote-tracking branch 'upstream/master' into 15041-Add-Custom-CI-Config-Path
* upstream/master: (12506 commits) Update CHANGELOG.md for 9.3.2 Update architecture.md Fix changelog entry file extension Fix head pipeline stored in merge request for external pipelines updated gitlab-ci.yml to compile locale Ignore JSON files generated from PO files Update mmap2 gem tha disables mmap_obj.gsub! as current implementation uses method that is no longer part of Ruby API Disable rainbow during SimpleExecutor specs to have consistence Slightly refactor pipeline schedules form in preparation for additions Resolve "Submitting reply to existing diff discussion using Cmd/Ctrl+Enter submits twice and refreshes page" Make the SimpleExecutor rescue exceptions in the executing Checks Resolve "Unable to access edit comment from dropdown menu in certain screen sizes" Update changelog item revert removal of requestAnimationFrame and move to a separate MR/discussion rename getEmojiCategoryMap and remove unnecessary parameter Action Buttons on Prio Labels working again by setting pointer events to none on… Remove 'contains' option from Commit.find_all Remove Gitlab::Git::Repository#find_all Use latest chrome and chrome driver in GitLab QA Polish sidebar toggle ...
Diffstat (limited to 'doc')
-rw-r--r--doc/README.md231
-rw-r--r--doc/administration/auth/README.md5
-rw-r--r--doc/administration/auth/authentiq.md69
-rw-r--r--doc/administration/auth/crowd.md68
-rw-r--r--doc/administration/auth/img/crowd_application.pngbin0 -> 55811 bytes
-rw-r--r--doc/administration/auth/img/okta_admin_panel.pngbin0 -> 26164 bytes
-rw-r--r--doc/administration/auth/img/okta_saml_settings.pngbin0 -> 25470 bytes
-rw-r--r--doc/administration/auth/ldap.md44
-rw-r--r--doc/administration/auth/okta.md160
-rw-r--r--doc/administration/build_artifacts.md91
-rw-r--r--doc/administration/container_registry.md126
-rw-r--r--doc/administration/custom_hooks.md31
-rw-r--r--doc/administration/environment_variables.md26
-rw-r--r--doc/administration/gitaly/index.md223
-rw-r--r--doc/administration/high_availability/README.md51
-rw-r--r--doc/administration/high_availability/database.md20
-rw-r--r--doc/administration/high_availability/gitlab.md6
-rw-r--r--doc/administration/high_availability/load_balancer.md37
-rw-r--r--doc/administration/high_availability/nfs.md68
-rw-r--r--doc/administration/high_availability/redis.md901
-rw-r--r--doc/administration/high_availability/redis_source.md367
-rw-r--r--doc/administration/housekeeping.md34
-rw-r--r--doc/administration/img/custom_hooks_error_msg.pngbin159486 -> 44922 bytes
-rw-r--r--doc/administration/img/high_availability/active-active-diagram.pngbin29607 -> 14649 bytes
-rw-r--r--doc/administration/img/high_availability/active-passive-diagram.pngbin24246 -> 11699 bytes
-rw-r--r--doc/administration/img/housekeeping_settings.pngbin27420 -> 12025 bytes
-rw-r--r--doc/administration/img/integration/plantuml-example.pngbin0 -> 33034 bytes
-rw-r--r--doc/administration/img/raketasks/check_repos_output.pngbin0 -> 19153 bytes
-rw-r--r--doc/administration/img/repository_storages_admin_ui.pngbin17081 -> 17760 bytes
-rw-r--r--doc/administration/integration/koding.md1
-rw-r--r--doc/administration/integration/plantuml.md97
-rw-r--r--doc/administration/integration/terminal.md85
-rw-r--r--doc/administration/job_artifacts.md162
-rw-r--r--doc/administration/logs.md39
-rw-r--r--doc/administration/monitoring/performance/gitlab_configuration.md40
-rw-r--r--doc/administration/monitoring/performance/grafana_configuration.md111
-rw-r--r--doc/administration/monitoring/performance/img/grafana_dashboard_dropdown.pngbin0 -> 7761 bytes
-rw-r--r--doc/administration/monitoring/performance/img/grafana_dashboard_import.pngbin0 -> 11836 bytes
-rw-r--r--doc/administration/monitoring/performance/img/grafana_data_source_configuration.pngbin0 -> 14700 bytes
-rw-r--r--doc/administration/monitoring/performance/img/grafana_data_source_empty.pngbin0 -> 11963 bytes
-rw-r--r--doc/administration/monitoring/performance/img/grafana_save_icon.pngbin0 -> 4619 bytes
-rw-r--r--doc/administration/monitoring/performance/img/metrics_gitlab_configuration_settings.pngbin0 -> 26169 bytes
-rw-r--r--doc/administration/monitoring/performance/img/request_profile_result.pngbin0 -> 3236 bytes
-rw-r--r--doc/administration/monitoring/performance/img/request_profiling_token.pngbin0 -> 10229 bytes
-rw-r--r--doc/administration/monitoring/performance/influxdb_configuration.md193
-rw-r--r--doc/administration/monitoring/performance/influxdb_schema.md97
-rw-r--r--doc/administration/monitoring/performance/introduction.md70
-rw-r--r--doc/administration/monitoring/performance/prometheus.md1
-rw-r--r--doc/administration/monitoring/performance/request_profiling.md16
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md47
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_monitor_exporter.md30
-rw-r--r--doc/administration/monitoring/prometheus/index.md170
-rw-r--r--doc/administration/monitoring/prometheus/node_exporter.md30
-rw-r--r--doc/administration/monitoring/prometheus/postgres_exporter.md30
-rw-r--r--doc/administration/monitoring/prometheus/redis_exporter.md33
-rw-r--r--doc/administration/operations.md7
-rw-r--r--doc/administration/operations/cleaning_up_redis_sessions.md52
-rw-r--r--doc/administration/operations/img/sidekiq_job_throttling.pngbin0 -> 32229 bytes
-rw-r--r--doc/administration/operations/moving_repositories.md180
-rw-r--r--doc/administration/operations/sidekiq_job_throttling.md33
-rw-r--r--doc/administration/operations/sidekiq_memory_killer.md40
-rw-r--r--doc/administration/operations/unicorn.md86
-rw-r--r--doc/administration/pages/index.md283
-rw-r--r--doc/administration/pages/source.md438
-rw-r--r--doc/administration/polling.md24
-rw-r--r--doc/administration/raketasks/check.md78
-rw-r--r--doc/administration/raketasks/github_import.md36
-rw-r--r--doc/administration/raketasks/ldap.md120
-rw-r--r--doc/administration/raketasks/maintenance.md221
-rw-r--r--doc/administration/reply_by_email.md364
-rw-r--r--doc/administration/reply_by_email_postfix_setup.md324
-rw-r--r--doc/administration/repository_checks.md10
-rw-r--r--doc/administration/repository_storage_paths.md105
-rw-r--r--doc/administration/repository_storages.md98
-rw-r--r--doc/administration/restart_gitlab.md2
-rw-r--r--doc/administration/troubleshooting/debug.md6
-rw-r--r--doc/api/README.md244
-rw-r--r--doc/api/access_requests.md34
-rw-r--r--doc/api/award_emoji.md188
-rw-r--r--doc/api/boards.md51
-rw-r--r--doc/api/branches.md75
-rw-r--r--doc/api/broadcast_messages.md30
-rw-r--r--doc/api/build_triggers.md119
-rw-r--r--doc/api/build_variables.md53
-rw-r--r--doc/api/builds.md611
-rw-r--r--doc/api/ci/builds.md2
-rw-r--r--doc/api/ci/lint.md4
-rw-r--r--doc/api/ci/runners.md8
-rw-r--r--doc/api/commits.md119
-rw-r--r--doc/api/deploy_key_multiple_projects.md10
-rw-r--r--doc/api/deploy_keys.md82
-rw-r--r--doc/api/deployments.md23
-rw-r--r--doc/api/environments.md (renamed from doc/api/enviroments.md)49
-rw-r--r--doc/api/events.md347
-rw-r--r--doc/api/features.md83
-rw-r--r--doc/api/groups.md155
-rw-r--r--doc/api/issues.md592
-rw-r--r--doc/api/jobs.md617
-rw-r--r--doc/api/keys.md6
-rw-r--r--doc/api/labels.md228
-rw-r--r--doc/api/members.md42
-rw-r--r--doc/api/merge_requests.md413
-rw-r--r--doc/api/milestones.md41
-rw-r--r--doc/api/namespaces.md15
-rw-r--r--doc/api/notes.md173
-rw-r--r--doc/api/notification_settings.md26
-rw-r--r--doc/api/oauth2.md8
-rw-r--r--doc/api/pipeline_schedules.md273
-rw-r--r--doc/api/pipeline_triggers.md172
-rw-r--r--doc/api/pipelines.md128
-rw-r--r--doc/api/project_snippets.md32
-rw-r--r--doc/api/projects.md700
-rw-r--r--doc/api/repositories.md96
-rw-r--r--doc/api/repository_files.md62
-rw-r--r--doc/api/runners.md46
-rw-r--r--doc/api/services.md236
-rw-r--r--doc/api/session.md18
-rw-r--r--doc/api/settings.md50
-rw-r--r--doc/api/sidekiq_metrics.md10
-rw-r--r--doc/api/snippets.md236
-rw-r--r--doc/api/system_hooks.md65
-rw-r--r--doc/api/tags.md51
-rw-r--r--doc/api/templates/gitignores.md579
-rw-r--r--doc/api/templates/gitlab_ci_ymls.md120
-rw-r--r--doc/api/templates/licenses.md (renamed from doc/api/licenses.md)10
-rw-r--r--doc/api/todos.md43
-rw-r--r--doc/api/users.md386
-rw-r--r--doc/api/v3_to_v4.md85
-rw-r--r--doc/api/version.md23
-rw-r--r--doc/articles/how_to_configure_ldap_gitlab_ce/img/gitlab_ou.pngbin0 -> 27877 bytes
-rw-r--r--doc/articles/how_to_configure_ldap_gitlab_ce/img/ldap_ou.gifbin0 -> 222162 bytes
-rw-r--r--doc/articles/how_to_configure_ldap_gitlab_ce/img/user_auth.gifbin0 -> 110971 bytes
-rw-r--r--doc/articles/how_to_configure_ldap_gitlab_ce/index.md266
-rw-r--r--doc/articles/how_to_install_git/index.md66
-rw-r--r--doc/articles/index.md25
-rw-r--r--doc/ci/README.md160
-rw-r--r--doc/ci/api/README.md2
-rw-r--r--doc/ci/api/builds.md2
-rw-r--r--doc/ci/api/runners.md2
-rw-r--r--doc/ci/autodeploy/img/auto_deploy_button.pngbin0 -> 43441 bytes
-rw-r--r--doc/ci/autodeploy/img/auto_deploy_dropdown.pngbin0 -> 99422 bytes
-rw-r--r--doc/ci/autodeploy/index.md71
-rw-r--r--doc/ci/build_artifacts/README.md5
-rw-r--r--doc/ci/docker/README.md4
-rw-r--r--doc/ci/docker/using_docker_build.md219
-rw-r--r--doc/ci/docker/using_docker_images.md123
-rw-r--r--doc/ci/enable_or_disable_ci.md18
-rw-r--r--doc/ci/environments.md679
-rw-r--r--doc/ci/examples/README.md66
-rw-r--r--doc/ci/examples/code_climate.md34
-rw-r--r--doc/ci/examples/deployment/README.md86
-rw-r--r--doc/ci/examples/deployment/composer-npm-deploy.md156
-rw-r--r--doc/ci/examples/php.md20
-rw-r--r--doc/ci/examples/test-and-deploy-python-application-to-heroku.md4
-rw-r--r--doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md6
-rw-r--r--doc/ci/examples/test-phoenix-application.md56
-rw-r--r--doc/ci/examples/test-scala-application.md45
-rw-r--r--doc/ci/git_submodules.md97
-rw-r--r--doc/ci/img/builds_tab.pngbin3047 -> 1956 bytes
-rw-r--r--doc/ci/img/cicd_pipeline_infograph.pngbin0 -> 32493 bytes
-rw-r--r--doc/ci/img/deployments_view.pngbin0 -> 19923 bytes
-rw-r--r--doc/ci/img/environments_available_staging.pngbin0 -> 10098 bytes
-rw-r--r--doc/ci/img/environments_dynamic_groups.pngbin0 -> 45349 bytes
-rw-r--r--doc/ci/img/environments_link_url.pngbin0 -> 12277 bytes
-rw-r--r--doc/ci/img/environments_link_url_deployments.pngbin0 -> 7490 bytes
-rw-r--r--doc/ci/img/environments_link_url_mr.pngbin0 -> 17947 bytes
-rw-r--r--doc/ci/img/environments_manual_action_builds.pngbin0 -> 11137 bytes
-rw-r--r--doc/ci/img/environments_manual_action_deployments.pngbin0 -> 12563 bytes
-rw-r--r--doc/ci/img/environments_manual_action_environments.pngbin0 -> 14914 bytes
-rw-r--r--doc/ci/img/environments_manual_action_pipelines.pngbin0 -> 16243 bytes
-rw-r--r--doc/ci/img/environments_manual_action_single_pipeline.pngbin0 -> 16576 bytes
-rw-r--r--doc/ci/img/environments_monitoring.pngbin0 -> 94408 bytes
-rw-r--r--doc/ci/img/environments_mr_review_app.pngbin0 -> 15366 bytes
-rw-r--r--doc/ci/img/environments_terminal_button_on_index.pngbin0 -> 79725 bytes
-rw-r--r--doc/ci/img/environments_terminal_button_on_show.pngbin0 -> 73210 bytes
-rw-r--r--doc/ci/img/environments_terminal_page.pngbin0 -> 117863 bytes
-rw-r--r--doc/ci/img/environments_view.pngbin0 -> 21155 bytes
-rw-r--r--doc/ci/img/features_settings.pngbin15809 -> 0 bytes
-rw-r--r--doc/ci/img/permissions_settings.pngbin0 -> 39194 bytes
-rw-r--r--doc/ci/img/pipelines-goal.svg4
-rw-r--r--doc/ci/img/pipelines.pngbin0 -> 6298 bytes
-rw-r--r--doc/ci/img/pipelines_grouped.pngbin0 -> 12937 bytes
-rw-r--r--doc/ci/img/pipelines_index.pngbin0 -> 36299 bytes
-rw-r--r--doc/ci/img/pipelines_mini_graph.pngbin0 -> 15404 bytes
-rw-r--r--doc/ci/img/pipelines_mini_graph_simple.pngbin0 -> 1637 bytes
-rw-r--r--doc/ci/img/pipelines_mini_graph_sorting.pngbin0 -> 10742 bytes
-rw-r--r--doc/ci/img/prometheus_environment_detail_with_metrics.pngbin0 -> 120479 bytes
-rw-r--r--doc/ci/img/types-of-pipelines.svg4
-rw-r--r--doc/ci/img/view_on_env_blob.pngbin0 -> 111663 bytes
-rw-r--r--doc/ci/img/view_on_env_mr.pngbin0 -> 1005195 bytes
-rw-r--r--doc/ci/pipelines.md242
-rw-r--r--doc/ci/quick_start/README.md91
-rw-r--r--doc/ci/quick_start/img/build_log.pngbin52482 -> 35261 bytes
-rw-r--r--doc/ci/quick_start/img/builds_status.pngbin41838 -> 19127 bytes
-rw-r--r--doc/ci/quick_start/img/new_commit.pngbin7587 -> 5584 bytes
-rw-r--r--doc/ci/quick_start/img/pipelines_status.pngbin89387 -> 22872 bytes
-rw-r--r--doc/ci/quick_start/img/runners_activated.pngbin22822 -> 18215 bytes
-rw-r--r--doc/ci/quick_start/img/single_commit_status_pending.pngbin29981 -> 13631 bytes
-rw-r--r--doc/ci/quick_start/img/status_pending.pngbin16205 -> 0 bytes
-rw-r--r--doc/ci/review_apps/img/review_apps_preview_in_mr.pngbin0 -> 11723 bytes
-rw-r--r--doc/ci/review_apps/index.md124
-rw-r--r--doc/ci/runners/README.md248
-rw-r--r--doc/ci/runners/img/shared_runners_admin.pngbin0 -> 29192 bytes
-rw-r--r--doc/ci/runners/project_specific.pngbin30196 -> 0 bytes
-rw-r--r--doc/ci/runners/shared_runner.pngbin17797 -> 0 bytes
-rw-r--r--doc/ci/services/mysql.md4
-rw-r--r--doc/ci/services/postgres.md4
-rw-r--r--doc/ci/services/redis.md2
-rw-r--r--doc/ci/ssh_keys/README.md24
-rw-r--r--doc/ci/triggers/README.md179
-rw-r--r--doc/ci/triggers/img/builds_page.pngbin76181 -> 20383 bytes
-rw-r--r--doc/ci/triggers/img/trigger_single_build.pngbin21152 -> 6585 bytes
-rw-r--r--doc/ci/triggers/img/trigger_variables.pngbin9315 -> 3637 bytes
-rw-r--r--doc/ci/triggers/img/triggers_page.pngbin12002 -> 20857 bytes
-rw-r--r--doc/ci/variables/README.md516
-rw-r--r--doc/ci/yaml/README.md661
-rw-r--r--doc/customization/branded_login_page/appearance.pngbin156228 -> 85263 bytes
-rw-r--r--doc/customization/branded_login_page/custom_sign_in.pngbin166674 -> 79288 bytes
-rw-r--r--doc/customization/branded_login_page/default_login_page.pngbin150538 -> 73004 bytes
-rw-r--r--doc/customization/branded_page_and_email_header.md15
-rw-r--r--doc/customization/branded_page_and_email_header/appearance.pngbin0 -> 10253 bytes
-rw-r--r--doc/customization/branded_page_and_email_header/custom_brand_header.pngbin0 -> 10014 bytes
-rw-r--r--doc/customization/branded_page_and_email_header/custom_email_header.pngbin0 -> 37472 bytes
-rw-r--r--doc/customization/libravatar.md4
-rw-r--r--doc/development/README.md28
-rw-r--r--doc/development/api_styleguide.md96
-rw-r--r--doc/development/architecture.md26
-rw-r--r--doc/development/background_migrations.md205
-rw-r--r--doc/development/build_test_package.md39
-rw-r--r--doc/development/changelog.md251
-rw-r--r--doc/development/ci_setup.md46
-rw-r--r--doc/development/code_review.md82
-rw-r--r--doc/development/doc_styleguide.md144
-rw-r--r--doc/development/fe_guide/accessibility.md13
-rw-r--r--doc/development/fe_guide/architecture.md22
-rw-r--r--doc/development/fe_guide/design_patterns.md78
-rw-r--r--doc/development/fe_guide/droplab/droplab.md258
-rw-r--r--doc/development/fe_guide/droplab/plugins/ajax.md37
-rw-r--r--doc/development/fe_guide/droplab/plugins/filter.md45
-rw-r--r--doc/development/fe_guide/droplab/plugins/input_setter.md60
-rw-r--r--doc/development/fe_guide/img/boards_diagram.pngbin0 -> 30538 bytes
-rw-r--r--doc/development/fe_guide/img/testing_triangle.pngbin0 -> 11836 bytes
-rw-r--r--doc/development/fe_guide/img/vue_arch.pngbin0 -> 9848 bytes
-rw-r--r--doc/development/fe_guide/index.md151
-rw-r--r--doc/development/fe_guide/performance.md94
-rw-r--r--doc/development/fe_guide/security.md92
-rw-r--r--doc/development/fe_guide/style_guide_js.md503
-rw-r--r--doc/development/fe_guide/style_guide_scss.md (renamed from doc/development/scss_styleguide.md)56
-rw-r--r--doc/development/fe_guide/testing.md254
-rw-r--r--doc/development/fe_guide/vue.md448
-rw-r--r--doc/development/feature_flags.md7
-rw-r--r--doc/development/foreign_keys.md63
-rw-r--r--doc/development/frontend.md225
-rw-r--r--doc/development/gemfile.md14
-rw-r--r--doc/development/gitlab_architecture_diagram.pngbin23831 -> 61667 bytes
-rw-r--r--doc/development/gotchas.md131
-rw-r--r--doc/development/i18n_guide.md256
-rw-r--r--doc/development/img/cache-hit.svg21
-rw-r--r--doc/development/img/cache-miss.svg24
-rw-r--r--doc/development/img/state-model-issue.pngbin0 -> 7713 bytes
-rw-r--r--doc/development/img/state-model-legend.pngbin0 -> 8496 bytes
-rw-r--r--doc/development/img/state-model-merge-request.pngbin0 -> 12459 bytes
-rw-r--r--doc/development/img/trigger_ss1.pngbin0 -> 106261 bytes
-rw-r--r--doc/development/img/trigger_ss2.pngbin0 -> 106671 bytes
-rw-r--r--doc/development/instrumentation.md12
-rw-r--r--doc/development/licensing.md10
-rw-r--r--doc/development/limit_ee_conflicts.md341
-rw-r--r--doc/development/merge_request_performance_guidelines.md12
-rw-r--r--doc/development/migration_style_guide.md223
-rw-r--r--doc/development/object_state_models.md25
-rw-r--r--doc/development/performance.md153
-rw-r--r--doc/development/polling.md56
-rw-r--r--doc/development/polymorphic_associations.md146
-rw-r--r--doc/development/post_deployment_migrations.md75
-rw-r--r--doc/development/profiling.md2
-rw-r--r--doc/development/query_recorder.md29
-rw-r--r--doc/development/rake_tasks.md44
-rw-r--r--doc/development/serializing_data.md84
-rw-r--r--doc/development/shell_commands.md8
-rw-r--r--doc/development/sidekiq_debugging.md13
-rw-r--r--doc/development/sidekiq_style_guide.md38
-rw-r--r--doc/development/single_table_inheritance.md18
-rw-r--r--doc/development/testing.md477
-rw-r--r--doc/development/ui_guide.md6
-rw-r--r--doc/development/ux_guide/animation.md57
-rw-r--r--doc/development/ux_guide/basics.md84
-rw-r--r--doc/development/ux_guide/components.md304
-rw-r--r--doc/development/ux_guide/copy.md188
-rw-r--r--doc/development/ux_guide/features.md57
-rw-r--r--doc/development/ux_guide/img/animation-autoscroll.gifbin0 -> 302217 bytes
-rw-r--r--doc/development/ux_guide/img/animation-dropdown.gifbin0 -> 22483 bytes
-rw-r--r--doc/development/ux_guide/img/animation-hover.gifbin0 -> 247388 bytes
-rw-r--r--doc/development/ux_guide/img/animation-quickupdate.gifbin0 -> 6441 bytes
-rw-r--r--doc/development/ux_guide/img/animation-reorder.gifbin0 -> 70515 bytes
-rw-r--r--doc/development/ux_guide/img/button-close--active.pngbin0 -> 1385 bytes
-rw-r--r--doc/development/ux_guide/img/button-close--hover.pngbin0 -> 1015 bytes
-rw-r--r--doc/development/ux_guide/img/button-close--resting.pngbin0 -> 1271 bytes
-rw-r--r--doc/development/ux_guide/img/button-danger--active.pngbin0 -> 1450 bytes
-rw-r--r--doc/development/ux_guide/img/button-danger--hover.pngbin0 -> 1095 bytes
-rw-r--r--doc/development/ux_guide/img/button-danger--resting.pngbin0 -> 1376 bytes
-rw-r--r--doc/development/ux_guide/img/button-info--active.pngbin0 -> 1442 bytes
-rw-r--r--doc/development/ux_guide/img/button-info--hover.pngbin0 -> 1079 bytes
-rw-r--r--doc/development/ux_guide/img/button-info--resting.pngbin0 -> 1296 bytes
-rw-r--r--doc/development/ux_guide/img/button-primary.pngbin0 -> 1550 bytes
-rw-r--r--doc/development/ux_guide/img/button-secondary.pngbin0 -> 2683 bytes
-rw-r--r--doc/development/ux_guide/img/button-spam--active.pngbin0 -> 1435 bytes
-rw-r--r--doc/development/ux_guide/img/button-spam--hover.pngbin0 -> 1108 bytes
-rw-r--r--doc/development/ux_guide/img/button-spam--resting.pngbin0 -> 1377 bytes
-rw-r--r--doc/development/ux_guide/img/button-success--active.pngbin0 -> 1510 bytes
-rw-r--r--doc/development/ux_guide/img/button-success--hover.pngbin0 -> 1151 bytes
-rw-r--r--doc/development/ux_guide/img/button-success--resting.pngbin0 -> 1447 bytes
-rw-r--r--doc/development/ux_guide/img/button-success-secondary--active.pngbin0 -> 1466 bytes
-rw-r--r--doc/development/ux_guide/img/button-success-secondary--hover.pngbin0 -> 1091 bytes
-rw-r--r--doc/development/ux_guide/img/button-success-secondary--resting.pngbin0 -> 1394 bytes
-rw-r--r--doc/development/ux_guide/img/button-warning--active.pngbin0 -> 1388 bytes
-rw-r--r--doc/development/ux_guide/img/button-warning--hover.pngbin0 -> 1040 bytes
-rw-r--r--doc/development/ux_guide/img/button-warning--resting.pngbin0 -> 1296 bytes
-rw-r--r--doc/development/ux_guide/img/color-blue.pngbin0 -> 3555 bytes
-rw-r--r--doc/development/ux_guide/img/color-green.pngbin0 -> 3852 bytes
-rw-r--r--doc/development/ux_guide/img/color-grey.pngbin0 -> 3523 bytes
-rw-r--r--doc/development/ux_guide/img/color-orange.pngbin0 -> 4480 bytes
-rw-r--r--doc/development/ux_guide/img/color-red.pngbin0 -> 3550 bytes
-rw-r--r--doc/development/ux_guide/img/color-textprimary.pngbin0 -> 2553 bytes
-rw-r--r--doc/development/ux_guide/img/color-textsecondary.pngbin0 -> 2956 bytes
-rw-r--r--doc/development/ux_guide/img/components-alerts.pngbin0 -> 27342 bytes
-rw-r--r--doc/development/ux_guide/img/components-anchorlinks.pngbin0 -> 30089 bytes
-rw-r--r--doc/development/ux_guide/img/components-contentblock.pngbin0 -> 14190 bytes
-rw-r--r--doc/development/ux_guide/img/components-counts.pngbin0 -> 2438 bytes
-rw-r--r--doc/development/ux_guide/img/components-coverblock.pngbin0 -> 10141 bytes
-rw-r--r--doc/development/ux_guide/img/components-dateexact.pngbin0 -> 4161 bytes
-rw-r--r--doc/development/ux_guide/img/components-daterelative.pngbin0 -> 4189 bytes
-rw-r--r--doc/development/ux_guide/img/components-dropdown.pngbin0 -> 31760 bytes
-rw-r--r--doc/development/ux_guide/img/components-fileholder.pngbin0 -> 3938 bytes
-rw-r--r--doc/development/ux_guide/img/components-horizontalform.pngbin0 -> 4327 bytes
-rw-r--r--doc/development/ux_guide/img/components-listinsidepanel.pngbin0 -> 3449 bytes
-rw-r--r--doc/development/ux_guide/img/components-listwithavatar.pngbin0 -> 5749 bytes
-rw-r--r--doc/development/ux_guide/img/components-listwithhover.pngbin0 -> 2860 bytes
-rw-r--r--doc/development/ux_guide/img/components-panels.pngbin0 -> 21822 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencehover.pngbin0 -> 6948 bytes
-rw-r--r--doc/development/ux_guide/img/components-referenceissues.pngbin0 -> 10009 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencelabels.pngbin0 -> 4108 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencemilestone.pngbin0 -> 2417 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencemrs.pngbin0 -> 8859 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencepeople.pngbin0 -> 5607 bytes
-rw-r--r--doc/development/ux_guide/img/components-rowcontentblock.pngbin0 -> 14315 bytes
-rw-r--r--doc/development/ux_guide/img/components-searchbox.pngbin0 -> 5292 bytes
-rw-r--r--doc/development/ux_guide/img/components-searchboxscoped.pngbin0 -> 9668 bytes
-rw-r--r--doc/development/ux_guide/img/components-simplelist.pngbin0 -> 2781 bytes
-rw-r--r--doc/development/ux_guide/img/components-table.pngbin0 -> 6081 bytes
-rw-r--r--doc/development/ux_guide/img/components-verticalform.pngbin0 -> 4964 bytes
-rw-r--r--doc/development/ux_guide/img/cursors-default.pngbin0 -> 567 bytes
-rw-r--r--doc/development/ux_guide/img/cursors-ibeam.pngbin0 -> 383 bytes
-rw-r--r--doc/development/ux_guide/img/cursors-move.pngbin0 -> 276 bytes
-rw-r--r--doc/development/ux_guide/img/cursors-panclosed.pngbin0 -> 483 bytes
-rw-r--r--doc/development/ux_guide/img/cursors-panopened.pngbin0 -> 622 bytes
-rw-r--r--doc/development/ux_guide/img/cursors-pointer.pngbin0 -> 574 bytes
-rw-r--r--doc/development/ux_guide/img/features-contextualnav.pngbin0 -> 5912 bytes
-rw-r--r--doc/development/ux_guide/img/features-emptystates.pngbin0 -> 61664 bytes
-rw-r--r--doc/development/ux_guide/img/features-filters.pngbin0 -> 3924 bytes
-rw-r--r--doc/development/ux_guide/img/features-globalnav.pngbin0 -> 5780 bytes
-rw-r--r--doc/development/ux_guide/img/harry-robison.pngbin0 -> 10712 bytes
-rw-r--r--doc/development/ux_guide/img/icon-add.pngbin0 -> 317 bytes
-rw-r--r--doc/development/ux_guide/img/icon-close.pngbin0 -> 501 bytes
-rw-r--r--doc/development/ux_guide/img/icon-edit.pngbin0 -> 546 bytes
-rw-r--r--doc/development/ux_guide/img/icon-notification.pngbin0 -> 543 bytes
-rw-r--r--doc/development/ux_guide/img/icon-rss.pngbin0 -> 834 bytes
-rw-r--r--doc/development/ux_guide/img/icon-subscribe.pngbin0 -> 760 bytes
-rw-r--r--doc/development/ux_guide/img/icon-trash.pngbin0 -> 398 bytes
-rw-r--r--doc/development/ux_guide/img/james-mackey.pngbin0 -> 11147 bytes
-rw-r--r--doc/development/ux_guide/img/karolina-plaskaty.pngbin0 -> 33498 bytes
-rw-r--r--doc/development/ux_guide/img/monospacefont-sample.pngbin0 -> 14282 bytes
-rw-r--r--doc/development/ux_guide/img/nazim-ramesh.pngbin0 -> 31163 bytes
-rw-r--r--doc/development/ux_guide/img/sourcesanspro-sample.pngbin0 -> 10948 bytes
-rw-r--r--doc/development/ux_guide/img/steven-lyons.pngbin0 -> 9323 bytes
-rw-r--r--doc/development/ux_guide/img/surfaces-contentitemtitle.pngbin0 -> 5142 bytes
-rw-r--r--doc/development/ux_guide/img/surfaces-header.pngbin0 -> 4095 bytes
-rw-r--r--doc/development/ux_guide/img/surfaces-systeminformationblock.pngbin0 -> 10423 bytes
-rw-r--r--doc/development/ux_guide/img/surfaces-ux.pngbin0 -> 4029 bytes
-rw-r--r--doc/development/ux_guide/img/tooltip-placement.pngbin0 -> 2071 bytes
-rw-r--r--doc/development/ux_guide/img/tooltip-usage.pngbin0 -> 5994 bytes
-rw-r--r--doc/development/ux_guide/index.md63
-rw-r--r--doc/development/ux_guide/principles.md17
-rw-r--r--doc/development/ux_guide/resources.md13
-rw-r--r--doc/development/ux_guide/surfaces.md47
-rw-r--r--doc/development/ux_guide/tips.md44
-rw-r--r--doc/development/ux_guide/users.md164
-rw-r--r--doc/development/what_requires_downtime.md237
-rw-r--r--doc/development/writing_documentation.md105
-rw-r--r--doc/downgrade_ee_to_ce/README.md7
-rw-r--r--doc/gitlab-basics/README.md6
-rw-r--r--doc/gitlab-basics/add-file.md28
-rw-r--r--doc/gitlab-basics/add-image.md50
-rw-r--r--doc/gitlab-basics/add-merge-request.md49
-rw-r--r--doc/gitlab-basics/basicsimages/add_new_merge_request.pngbin9003 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/add_sshkey.pngbin1394 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/branch_info.pngbin7572 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/branch_name.pngbin2137 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/branches.pngbin3548 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/button-create-mr.pngbin5927 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/click-on-new-group.pngbin1957 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/commit_changes.pngbin4941 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/commit_message.pngbin5103 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/commits.pngbin4112 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/compare_branches.pngbin1520 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/create_file.pngbin2451 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/create_group.pngbin3184 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/edit_file.pngbin2221 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/file_located.pngbin3078 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/file_name.pngbin2412 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/find_file.pngbin8426 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/find_group.pngbin5897 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/fork.pngbin896 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/group_info.pngbin15479 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/groups.pngbin4752 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/https.pngbin2822 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/image_file.pngbin2796 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/issue_title.pngbin8311 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/issues.pngbin4153 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/key.pngbin1177 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/merge_requests.pngbin4213 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/new_issue.pngbin2974 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/new_merge_request.pngbin3162 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/new_project.pngbin2234 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/newbranch.pngbin1244 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/paste_sshkey.pngbin7699 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/profile_settings.pngbin1101 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/project_info.pngbin21041 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/select-group.pngbin6034 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/select-group2.pngbin5040 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/select_branch.pngbin11207 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/select_project.pngbin16176 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/settings.pngbin4149 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/shh_keys.pngbin4782 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/submit_new_issue.pngbin8644 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/title_description_mr.pngbin11919 -> 0 bytes
-rw-r--r--doc/gitlab-basics/basicsimages/white_space.pngbin2192 -> 0 bytes
-rw-r--r--doc/gitlab-basics/command-line-commands.md28
-rw-r--r--doc/gitlab-basics/create-branch.md43
-rw-r--r--doc/gitlab-basics/create-group.md53
-rw-r--r--doc/gitlab-basics/create-issue.md27
-rw-r--r--doc/gitlab-basics/create-project.md33
-rw-r--r--doc/gitlab-basics/create-your-ssh-keys.md38
-rw-r--r--doc/gitlab-basics/fork-project.md19
-rw-r--r--doc/gitlab-basics/img/create_new_group_info.pngbin0 -> 105173 bytes
-rw-r--r--doc/gitlab-basics/img/create_new_group_sidebar.pngbin0 -> 2682 bytes
-rw-r--r--doc/gitlab-basics/img/create_new_project_button.pngbin0 -> 3702 bytes
-rw-r--r--doc/gitlab-basics/img/create_new_project_from_group.pngbin0 -> 3194 bytes
-rw-r--r--doc/gitlab-basics/img/create_new_project_info.pngbin0 -> 20385 bytes
-rw-r--r--doc/gitlab-basics/img/fork_choose_namespace.pngbin0 -> 13674 bytes
-rw-r--r--doc/gitlab-basics/img/fork_new.pngbin0 -> 10722 bytes
-rw-r--r--doc/gitlab-basics/img/merge_request_new.pngbin0 -> 2234 bytes
-rw-r--r--doc/gitlab-basics/img/merge_request_page.pngbin0 -> 33801 bytes
-rw-r--r--doc/gitlab-basics/img/merge_request_select_branch.pngbin0 -> 20332 bytes
-rw-r--r--doc/gitlab-basics/img/new_issue_button.pngbin0 -> 2010 bytes
-rw-r--r--doc/gitlab-basics/img/new_issue_page.pngbin0 -> 21386 bytes
-rw-r--r--doc/gitlab-basics/img/profile_settings.pngbin0 -> 5842 bytes
-rw-r--r--doc/gitlab-basics/img/profile_settings_ssh_keys.pngbin0 -> 16531 bytes
-rw-r--r--doc/gitlab-basics/img/profile_settings_ssh_keys_paste_pub.pngbin0 -> 13447 bytes
-rw-r--r--doc/gitlab-basics/img/profile_settings_ssh_keys_single_key.pngbin0 -> 24639 bytes
-rw-r--r--doc/gitlab-basics/img/profile_settings_ssh_keys_title.pngbin0 -> 1872 bytes
-rw-r--r--doc/gitlab-basics/img/project_clone_url.pngbin0 -> 14978 bytes
-rw-r--r--doc/gitlab-basics/img/project_navbar.pngbin0 -> 3259 bytes
-rw-r--r--doc/gitlab-basics/img/public_file_link.png (renamed from doc/gitlab-basics/basicsimages/public_file_link.png)bin3023 -> 3023 bytes
-rw-r--r--doc/gitlab-basics/img/select_group_dropdown.pngbin0 -> 3489 bytes
-rw-r--r--doc/gitlab-basics/start-using-git.md20
-rw-r--r--doc/incoming_email/README.md303
-rw-r--r--doc/incoming_email/postfix.md322
-rw-r--r--doc/install/README.md34
-rw-r--r--doc/install/database_mysql.md271
-rw-r--r--doc/install/digitaloceandocker.md139
-rw-r--r--doc/install/google-protobuf.md26
-rw-r--r--doc/install/google_cloud_platform/img/change_admin_passwd_email.pngbin0 -> 7193 bytes
-rw-r--r--doc/install/google_cloud_platform/img/chrome_not_secure_page.pngbin0 -> 21705 bytes
-rw-r--r--doc/install/google_cloud_platform/img/gcp_gitlab_being_deployed.pngbin0 -> 23486 bytes
-rw-r--r--doc/install/google_cloud_platform/img/gcp_gitlab_overview.pngbin0 -> 42028 bytes
-rw-r--r--doc/install/google_cloud_platform/img/gcp_landing.pngbin0 -> 59912 bytes
-rw-r--r--doc/install/google_cloud_platform/img/gcp_launcher_console_home_page.pngbin0 -> 42090 bytes
-rw-r--r--doc/install/google_cloud_platform/img/gcp_search_for_gitlab.pngbin0 -> 7648 bytes
-rw-r--r--doc/install/google_cloud_platform/img/gitlab_deployed_page.pngbin0 -> 35573 bytes
-rw-r--r--doc/install/google_cloud_platform/img/gitlab_first_sign_in.pngbin0 -> 20054 bytes
-rw-r--r--doc/install/google_cloud_platform/img/gitlab_launch_button.pngbin0 -> 5198 bytes
-rw-r--r--doc/install/google_cloud_platform/img/new_gitlab_deployment_settings.pngbin0 -> 50014 bytes
-rw-r--r--doc/install/google_cloud_platform/img/ssh_via_button.pngbin0 -> 3062 bytes
-rw-r--r--doc/install/google_cloud_platform/index.md172
-rw-r--r--doc/install/installation.md165
-rw-r--r--doc/install/kubernetes/gitlab_chart.md476
-rw-r--r--doc/install/kubernetes/gitlab_runner_chart.md178
-rw-r--r--doc/install/kubernetes/index.md47
-rw-r--r--doc/install/relative_url.md8
-rw-r--r--doc/install/requirements.md110
-rw-r--r--doc/integration/README.md23
-rw-r--r--doc/integration/auth0.md9
-rw-r--r--doc/integration/azure.md6
-rw-r--r--doc/integration/bitbucket.md124
-rw-r--r--doc/integration/cas.md9
-rw-r--r--doc/integration/chat_commands.md1
-rw-r--r--doc/integration/crowd.md59
-rw-r--r--doc/integration/external-issue-tracker.md8
-rw-r--r--doc/integration/facebook.md6
-rw-r--r--doc/integration/github.md78
-rw-r--r--doc/integration/gitlab.md16
-rw-r--r--doc/integration/google.md21
-rw-r--r--doc/integration/img/akismet_settings.pngbin26625 -> 16923 bytes
-rw-r--r--doc/integration/img/bitbucket_oauth_keys.pngbin12073 -> 5149 bytes
-rw-r--r--doc/integration/img/bitbucket_oauth_settings_page.pngbin82818 -> 28719 bytes
-rw-r--r--doc/integration/img/enabled-oauth-sign-in-sources.pngbin21767 -> 13304 bytes
-rw-r--r--doc/integration/img/facebook_api_keys.pngbin85832 -> 42308 bytes
-rw-r--r--doc/integration/img/facebook_app_settings.pngbin68086 -> 35876 bytes
-rw-r--r--doc/integration/img/facebook_website_url.pngbin19823 -> 9620 bytes
-rw-r--r--doc/integration/img/github_app.pngbin55591 -> 29330 bytes
-rw-r--r--doc/integration/img/gitlab_app.pngbin30963 -> 15402 bytes
-rw-r--r--doc/integration/img/gmail_action_buttons_for_gitlab.pngbin16020 -> 11573 bytes
-rw-r--r--doc/integration/img/google_app.pngbin29154 -> 19168 bytes
-rw-r--r--doc/integration/img/oauth_provider_admin_application.pngbin33440 -> 17082 bytes
-rw-r--r--doc/integration/img/oauth_provider_application_form.pngbin23048 -> 12566 bytes
-rw-r--r--doc/integration/img/oauth_provider_application_id_secret.pngbin27673 -> 15293 bytes
-rw-r--r--doc/integration/img/oauth_provider_authorized_application.pngbin26622 -> 14668 bytes
-rw-r--r--doc/integration/img/oauth_provider_user_wide_applications.pngbin33337 -> 17526 bytes
-rw-r--r--doc/integration/img/spam_log.pngbin187190 -> 50996 bytes
-rw-r--r--doc/integration/img/submit_issue.pngbin174556 -> 45962 bytes
-rw-r--r--doc/integration/img/twitter_app_api_keys.pngbin36921 -> 24577 bytes
-rw-r--r--doc/integration/img/twitter_app_details.pngbin64686 -> 40392 bytes
-rw-r--r--doc/integration/jira.md4
-rw-r--r--doc/integration/ldap.md4
-rw-r--r--doc/integration/oauth2_generic.md65
-rw-r--r--doc/integration/oauth_provider.md8
-rw-r--r--doc/integration/omniauth.md14
-rw-r--r--doc/integration/openid_connect_provider.md47
-rw-r--r--doc/integration/saml.md38
-rw-r--r--doc/integration/shibboleth.md16
-rw-r--r--doc/integration/slash_commands.md14
-rw-r--r--doc/integration/twitter.md6
-rw-r--r--doc/intro/README.md6
-rw-r--r--doc/migrate_ci_to_ce/README.md58
-rw-r--r--doc/monitoring/health_check.md67
-rw-r--r--doc/monitoring/img/health_check_token.pngbin6630 -> 0 bytes
-rw-r--r--doc/monitoring/performance/gitlab_configuration.md41
-rw-r--r--doc/monitoring/performance/grafana_configuration.md112
-rw-r--r--doc/monitoring/performance/img/grafana_dashboard_dropdown.pngbin14368 -> 7761 bytes
-rw-r--r--doc/monitoring/performance/img/grafana_dashboard_import.pngbin18267 -> 11836 bytes
-rw-r--r--doc/monitoring/performance/img/grafana_data_source_configuration.pngbin26060 -> 14700 bytes
-rw-r--r--doc/monitoring/performance/img/grafana_data_source_empty.pngbin21821 -> 11963 bytes
-rw-r--r--doc/monitoring/performance/img/grafana_save_icon.pngbin9107 -> 4619 bytes
-rw-r--r--doc/monitoring/performance/img/metrics_gitlab_configuration_settings.pngbin37228 -> 21387 bytes
-rw-r--r--doc/monitoring/performance/influxdb_configuration.md194
-rw-r--r--doc/monitoring/performance/influxdb_schema.md98
-rw-r--r--doc/monitoring/performance/introduction.md66
-rw-r--r--doc/operations/README.md6
-rw-r--r--doc/operations/cleaning_up_redis_sessions.md53
-rw-r--r--doc/operations/moving_repositories.md181
-rw-r--r--doc/operations/sidekiq_memory_killer.md41
-rw-r--r--doc/operations/unicorn.md87
-rw-r--r--doc/pages/README.md1
-rw-r--r--doc/pages/administration.md1
-rw-r--r--doc/pages/getting_started_part_one.md1
-rw-r--r--doc/pages/getting_started_part_three.md1
-rw-r--r--doc/pages/getting_started_part_two.md1
-rw-r--r--doc/profile/2fa_u2f_authenticate.pngbin54413 -> 0 bytes
-rw-r--r--doc/profile/2fa_u2f_register.pngbin112414 -> 0 bytes
-rw-r--r--doc/profile/README.md7
-rw-r--r--doc/profile/preferences.md44
-rw-r--r--doc/profile/two_factor_authentication.md128
-rw-r--r--doc/project_services/bamboo.md61
-rw-r--r--doc/project_services/bugzilla.md18
-rw-r--r--doc/project_services/builds_emails.md16
-rw-r--r--doc/project_services/emails_on_push.md18
-rw-r--r--doc/project_services/hipchat.md55
-rw-r--r--doc/project_services/img/builds_emails_service.pngbin33943 -> 0 bytes
-rw-r--r--doc/project_services/img/emails_on_push_service.pngbin98160 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_add_gitlab_commit_message.pngbin46590 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_add_user_to_group.pngbin41994 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_create_new_group.pngbin32934 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_create_new_group_name.pngbin9054 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_create_new_user.pngbin21081 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_group_access.pngbin32210 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_issue_closed.pngbin77028 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_issue_reference.pngbin36188 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_issues_workflow.pngbin87067 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_merge_request_close.pngbin102835 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_project_name.pngbin41572 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_reference_commit_message_in_jira_issue.pngbin33706 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_service.pngbin56834 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_service_close_issue.pngbin79569 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_service_page.pngbin36280 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_submit_gitlab_merge_request.pngbin51913 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_user_management_link.pngbin43095 -> 0 bytes
-rw-r--r--doc/project_services/img/jira_workflow_screenshot.pngbin111093 -> 0 bytes
-rw-r--r--doc/project_services/img/redmine_configuration.pngbin16973 -> 0 bytes
-rw-r--r--doc/project_services/img/services_templates_redmine_example.pngbin13936 -> 0 bytes
-rw-r--r--doc/project_services/img/slack_configuration.pngbin75762 -> 0 bytes
-rw-r--r--doc/project_services/irker.md52
-rw-r--r--doc/project_services/jira.md247
-rw-r--r--doc/project_services/kubernetes.md1
-rw-r--r--doc/project_services/mattermost.md1
-rw-r--r--doc/project_services/mattermost_slash_commands.md1
-rw-r--r--doc/project_services/project_services.md56
-rw-r--r--doc/project_services/redmine.md22
-rw-r--r--doc/project_services/services_templates.md26
-rw-r--r--doc/project_services/slack.md51
-rw-r--r--doc/project_services/slack_slash_commands.md1
-rw-r--r--doc/public_access/img/restrict_visibility_levels.pngbin0 -> 24593 bytes
-rw-r--r--doc/public_access/public_access.md9
-rw-r--r--doc/raketasks/README.md3
-rw-r--r--doc/raketasks/backup_hrz.pngbin8907 -> 11444 bytes
-rw-r--r--doc/raketasks/backup_restore.md321
-rw-r--r--doc/raketasks/check.md62
-rw-r--r--doc/raketasks/check_repos_output.pngbin35333 -> 0 bytes
-rw-r--r--doc/raketasks/features.md2
-rw-r--r--doc/raketasks/maintenance.md189
-rw-r--r--doc/raketasks/user_management.md94
-rw-r--r--doc/security/img/two_factor_authentication_group_settings.pngbin0 -> 44874 bytes
-rw-r--r--doc/security/img/two_factor_authentication_settings.pngbin16807 -> 9941 bytes
-rw-r--r--doc/security/two_factor_authentication.md17
-rw-r--r--doc/security/webhooks.md4
-rw-r--r--doc/ssh/README.md238
-rw-r--r--doc/system_hooks/system_hooks.md84
-rw-r--r--doc/topics/authentication/index.md48
-rw-r--r--doc/topics/git/index.md66
-rw-r--r--doc/topics/index.md16
-rw-r--r--doc/university/README.md63
-rw-r--r--doc/university/bookclub/booklist.md113
-rw-r--r--doc/university/bookclub/index.md19
-rw-r--r--doc/university/glossary/README.md390
-rw-r--r--doc/university/high-availability/aws/README.md22
-rw-r--r--doc/university/high-availability/aws/img/auto-scaling-det.pngbin106157 -> 29970 bytes
-rw-r--r--doc/university/high-availability/aws/img/db-subnet-group.pngbin98632 -> 29306 bytes
-rw-r--r--doc/university/high-availability/aws/img/ec-subnet.pngbin91922 -> 28405 bytes
-rw-r--r--doc/university/high-availability/aws/img/elastic-file-system.pngbin109719 -> 34582 bytes
-rw-r--r--doc/university/high-availability/aws/img/ig-rt.pngbin42022 -> 12547 bytes
-rw-r--r--doc/university/high-availability/aws/img/ig.pngbin26220 -> 8149 bytes
-rw-r--r--doc/university/high-availability/aws/img/instance_specs.pngbin40938 -> 11525 bytes
-rw-r--r--doc/university/high-availability/aws/img/new_vpc.pngbin54072 -> 15696 bytes
-rw-r--r--doc/university/high-availability/aws/img/policies.pngbin132366 -> 39845 bytes
-rw-r--r--doc/university/high-availability/aws/img/rds-net-opt.pngbin54996 -> 16347 bytes
-rw-r--r--doc/university/high-availability/aws/img/rds-sec-group.pngbin43950 -> 11584 bytes
-rw-r--r--doc/university/high-availability/aws/img/redis-cluster-det.pngbin81524 -> 23761 bytes
-rw-r--r--doc/university/high-availability/aws/img/redis-net.pngbin100700 -> 27261 bytes
-rw-r--r--doc/university/high-availability/aws/img/route_table.pngbin39611 -> 12088 bytes
-rw-r--r--doc/university/high-availability/aws/img/subnet.pngbin56466 -> 17077 bytes
-rw-r--r--doc/university/support/README.md35
-rwxr-xr-xdoc/university/training/gitlab_flow.md53
-rw-r--r--doc/university/training/gitlab_flow/feature_branches.pngbin0 -> 6202 bytes
-rw-r--r--doc/university/training/gitlab_flow/production_branch.pngbin0 -> 7293 bytes
-rw-r--r--doc/university/training/gitlab_flow/release_branches.pngbin0 -> 12775 bytes
-rwxr-xr-xdoc/university/training/index.md6
-rw-r--r--doc/university/training/logo.pngbin0 -> 8940 bytes
-rwxr-xr-xdoc/university/training/topics/additional_resources.md8
-rwxr-xr-xdoc/university/training/topics/agile_git.md33
-rwxr-xr-xdoc/university/training/topics/bisect.md81
-rwxr-xr-xdoc/university/training/topics/cherry_picking.md39
-rwxr-xr-xdoc/university/training/topics/env_setup.md60
-rwxr-xr-xdoc/university/training/topics/explore_gitlab.md10
-rwxr-xr-xdoc/university/training/topics/feature_branching.md32
-rwxr-xr-xdoc/university/training/topics/getting_started.md95
-rwxr-xr-xdoc/university/training/topics/git_add.md33
-rwxr-xr-xdoc/university/training/topics/git_intro.md24
-rwxr-xr-xdoc/university/training/topics/git_log.md57
-rwxr-xr-xdoc/university/training/topics/gitlab_flow.md53
-rwxr-xr-xdoc/university/training/topics/merge_conflicts.md70
-rwxr-xr-xdoc/university/training/topics/merge_requests.md43
-rwxr-xr-xdoc/university/training/topics/rollback_commits.md81
-rwxr-xr-xdoc/university/training/topics/stash.md86
-rwxr-xr-xdoc/university/training/topics/subtree.md55
-rwxr-xr-xdoc/university/training/topics/tags.md38
-rwxr-xr-xdoc/university/training/topics/unstage.md31
-rwxr-xr-xdoc/university/training/user_training.md392
-rw-r--r--doc/update/2.6-to-3.0.md2
-rw-r--r--doc/update/2.9-to-3.0.md2
-rw-r--r--doc/update/3.0-to-3.1.md2
-rw-r--r--doc/update/3.1-to-4.0.md2
-rw-r--r--doc/update/4.0-to-4.1.md2
-rw-r--r--doc/update/4.1-to-4.2.md2
-rw-r--r--doc/update/4.2-to-5.0.md2
-rw-r--r--doc/update/5.0-to-5.1.md2
-rw-r--r--doc/update/5.1-to-5.2.md2
-rw-r--r--doc/update/5.1-to-5.4.md2
-rw-r--r--doc/update/5.1-to-6.0.md2
-rw-r--r--doc/update/5.2-to-5.3.md2
-rw-r--r--doc/update/5.3-to-5.4.md2
-rw-r--r--doc/update/5.4-to-6.0.md2
-rw-r--r--doc/update/6.0-to-6.1.md2
-rw-r--r--doc/update/6.1-to-6.2.md2
-rw-r--r--doc/update/6.2-to-6.3.md2
-rw-r--r--doc/update/6.3-to-6.4.md2
-rw-r--r--doc/update/6.4-to-6.5.md2
-rw-r--r--doc/update/6.5-to-6.6.md2
-rw-r--r--doc/update/6.6-to-6.7.md2
-rw-r--r--doc/update/6.7-to-6.8.md2
-rw-r--r--doc/update/6.8-to-6.9.md2
-rw-r--r--doc/update/6.9-to-7.0.md2
-rw-r--r--doc/update/6.x-or-7.x-to-7.14.md4
-rw-r--r--doc/update/7.0-to-7.1.md4
-rw-r--r--doc/update/7.1-to-7.2.md4
-rw-r--r--doc/update/7.10-to-7.11.md4
-rw-r--r--doc/update/7.11-to-7.12.md4
-rw-r--r--doc/update/7.12-to-7.13.md4
-rw-r--r--doc/update/7.13-to-7.14.md4
-rw-r--r--doc/update/7.14-to-8.0.md4
-rw-r--r--doc/update/7.2-to-7.3.md4
-rw-r--r--doc/update/7.3-to-7.4.md9
-rw-r--r--doc/update/7.4-to-7.5.md8
-rw-r--r--doc/update/7.5-to-7.6.md13
-rw-r--r--doc/update/7.6-to-7.7.md15
-rw-r--r--doc/update/7.7-to-7.8.md13
-rw-r--r--doc/update/7.8-to-7.9.md13
-rw-r--r--doc/update/7.9-to-7.10.md13
-rw-r--r--doc/update/8.0-to-8.1.md4
-rw-r--r--doc/update/8.1-to-8.2.md4
-rw-r--r--doc/update/8.10-to-8.11.md6
-rw-r--r--doc/update/8.11-to-8.12.md8
-rw-r--r--doc/update/8.12-to-8.13.md12
-rw-r--r--doc/update/8.13-to-8.14.md209
-rw-r--r--doc/update/8.14-to-8.15.md239
-rw-r--r--doc/update/8.15-to-8.16.md241
-rw-r--r--doc/update/8.16-to-8.17.md268
-rw-r--r--doc/update/8.17-to-9.0.md341
-rw-r--r--doc/update/8.2-to-8.3.md12
-rw-r--r--doc/update/8.3-to-8.4.md6
-rw-r--r--doc/update/8.4-to-8.5.md6
-rw-r--r--doc/update/8.5-to-8.6.md4
-rw-r--r--doc/update/8.6-to-8.7.md4
-rw-r--r--doc/update/8.7-to-8.8.md4
-rw-r--r--doc/update/8.8-to-8.9.md4
-rw-r--r--doc/update/8.9-to-8.10.md4
-rw-r--r--doc/update/9.0-to-9.1.md390
-rw-r--r--doc/update/9.1-to-9.2.md288
-rw-r--r--doc/update/9.2-to-9.3.md305
-rw-r--r--doc/update/9.3-to-9.4.md317
-rw-r--r--doc/update/README.md32
-rw-r--r--doc/update/patch_versions.md50
-rw-r--r--doc/update/upgrader.md2
-rw-r--r--doc/update/upgrading_postgresql_using_slony.md482
-rw-r--r--doc/user/account/security.md4
-rw-r--r--doc/user/account/two_factor_authentication.md69
-rw-r--r--doc/user/admin_area/img/admin_labels.pngbin91459 -> 23063 bytes
-rw-r--r--doc/user/admin_area/img/cohorts.pngbin0 -> 439635 bytes
-rw-r--r--doc/user/admin_area/monitoring/convdev.md29
-rw-r--r--doc/user/admin_area/monitoring/health_check.md108
-rw-r--r--doc/user/admin_area/monitoring/img/convdev_index.pngbin0 -> 31012 bytes
-rw-r--r--doc/user/admin_area/monitoring/img/health_check_token.pngbin0 -> 4923 bytes
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md28
-rw-r--r--doc/user/admin_area/settings/img/access_restrictions.pngbin7435 -> 3794 bytes
-rw-r--r--doc/user/admin_area/settings/img/admin_area_default_artifacts_expiration.pngbin0 -> 14656 bytes
-rw-r--r--doc/user/admin_area/settings/img/admin_area_maximum_artifacts_size.pngbin6227 -> 12917 bytes
-rw-r--r--doc/user/admin_area/settings/img/admin_area_settings_button.pngbin9184 -> 4403 bytes
-rw-r--r--doc/user/admin_area/settings/img/domain_blacklist.pngbin34684 -> 13606 bytes
-rw-r--r--doc/user/admin_area/settings/img/restricted_url.pngbin47539 -> 18202 bytes
-rw-r--r--doc/user/admin_area/settings/sign_up_restrictions.md24
-rw-r--r--doc/user/admin_area/settings/usage_statistics.md66
-rw-r--r--doc/user/admin_area/user_cohorts.md37
-rw-r--r--doc/user/award_emojis.md51
-rw-r--r--doc/user/discussions/img/btn_new_issue_for_all_discussions.pngbin0 -> 29007 bytes
-rw-r--r--doc/user/discussions/img/comment_type_toggle.gifbin0 -> 70796 bytes
-rw-r--r--doc/user/discussions/img/discussion_comment.pngbin0 -> 57189 bytes
-rw-r--r--doc/user/discussions/img/discussion_view.pngbin0 -> 73821 bytes
-rw-r--r--doc/user/discussions/img/discussions_resolved.pngbin0 -> 4152 bytes
-rw-r--r--doc/user/discussions/img/new_issue_for_discussion.pngbin0 -> 39563 bytes
-rw-r--r--doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved.pngbin0 -> 17888 bytes
-rw-r--r--doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved_msg.pngbin0 -> 4962 bytes
-rw-r--r--doc/user/discussions/img/preview_issue_for_discussion.pngbin0 -> 82412 bytes
-rw-r--r--doc/user/discussions/img/preview_issue_for_discussions.pngbin0 -> 143871 bytes
-rw-r--r--doc/user/discussions/img/resolve_comment_button.pngbin0 -> 4722 bytes
-rw-r--r--doc/user/discussions/img/resolve_discussion_button.pngbin0 -> 4683 bytes
-rw-r--r--doc/user/discussions/img/resolve_discussion_issue_notice.pngbin0 -> 10307 bytes
-rw-r--r--doc/user/discussions/img/resolve_discussion_open_issue.pngbin0 -> 20967 bytes
-rw-r--r--doc/user/discussions/index.md150
-rw-r--r--doc/user/group/subgroups/img/create_new_group.pngbin0 -> 18503 bytes
-rw-r--r--doc/user/group/subgroups/img/create_subgroup_button.pngbin0 -> 8402 bytes
-rw-r--r--doc/user/group/subgroups/img/group_members.pngbin0 -> 48240 bytes
-rw-r--r--doc/user/group/subgroups/img/mention_subgroups.pngbin0 -> 39666 bytes
-rw-r--r--doc/user/group/subgroups/index.md179
-rw-r--r--doc/user/img/award_emoji_comment_awarded.pngbin0 -> 19159 bytes
-rw-r--r--doc/user/img/award_emoji_comment_picker.pngbin0 -> 72883 bytes
-rw-r--r--doc/user/img/award_emoji_select.pngbin0 -> 17827 bytes
-rw-r--r--doc/user/img/award_emoji_votes_sort_options.pngbin0 -> 99941 bytes
-rw-r--r--doc/user/img/gitlab_snippet.pngbin0 -> 34355 bytes
-rw-r--r--doc/user/img/markdown_logo.pngbin9509 -> 4421 bytes
-rw-r--r--doc/user/markdown.md287
-rw-r--r--doc/user/permissions.md66
-rw-r--r--doc/user/profile/account/delete_account.md35
-rw-r--r--doc/user/profile/account/img/2fa.png (renamed from doc/profile/2fa.png)bin22047 -> 22047 bytes
-rw-r--r--doc/user/profile/account/img/2fa_auth.png (renamed from doc/profile/2fa_auth.png)bin14535 -> 14535 bytes
-rw-r--r--doc/user/profile/account/img/2fa_u2f_authenticate.pngbin0 -> 17582 bytes
-rw-r--r--doc/user/profile/account/img/2fa_u2f_register.pngbin0 -> 35186 bytes
-rw-r--r--doc/user/profile/account/index.md5
-rw-r--r--doc/user/profile/account/two_factor_authentication.md223
-rw-r--r--doc/user/profile/img/personal_access_tokens.pngbin0 -> 18555 bytes
-rw-r--r--doc/user/profile/personal_access_tokens.md57
-rw-r--r--doc/user/profile/preferences.md64
-rw-r--r--doc/user/project/builds/artifacts.md137
-rw-r--r--doc/user/project/builds/img/build_artifacts_browser.pngbin8365 -> 0 bytes
-rw-r--r--doc/user/project/builds/img/build_artifacts_browser_button.pngbin11041 -> 0 bytes
-rw-r--r--doc/user/project/builds/img/build_artifacts_builds_page.pngbin55625 -> 0 bytes
-rw-r--r--doc/user/project/builds/img/build_artifacts_pipelines_page.pngbin73038 -> 0 bytes
-rw-r--r--doc/user/project/builds/img/build_latest_artifacts_browser.pngbin26617 -> 0 bytes
-rw-r--r--doc/user/project/container_registry.md71
-rw-r--r--doc/user/project/cycle_analytics.md40
-rw-r--r--doc/user/project/git_attributes.md22
-rw-r--r--doc/user/project/img/container_registry_enable.pngbin5526 -> 3057 bytes
-rw-r--r--doc/user/project/img/container_registry_panel.pngbin96315 -> 0 bytes
-rw-r--r--doc/user/project/img/container_registry_tab.pngbin7284 -> 3800 bytes
-rw-r--r--doc/user/project/img/cycle_analytics_landing_page.pngbin66080 -> 42117 bytes
-rw-r--r--doc/user/project/img/description_templates.pngbin20444 -> 7903 bytes
-rw-r--r--doc/user/project/img/issue_board.pngbin275093 -> 76461 bytes
-rw-r--r--doc/user/project/img/issue_board_add_list.pngbin22391 -> 23632 bytes
-rw-r--r--doc/user/project/img/issue_board_search_backlog.pngbin25948 -> 0 bytes
-rw-r--r--doc/user/project/img/issue_board_system_notes.pngbin20637 -> 4899 bytes
-rw-r--r--doc/user/project/img/issue_board_welcome_message.pngbin78694 -> 120751 bytes
-rw-r--r--doc/user/project/img/issue_boards_add_issues_modal.pngbin0 -> 177057 bytes
-rw-r--r--doc/user/project/img/issue_boards_remove_issue.pngbin0 -> 135168 bytes
-rw-r--r--doc/user/project/img/koding_build-in-progress.pngbin70949 -> 21953 bytes
-rw-r--r--doc/user/project/img/koding_build-logs.pngbin263623 -> 91364 bytes
-rw-r--r--doc/user/project/img/koding_build-success.pngbin304666 -> 73008 bytes
-rw-r--r--doc/user/project/img/koding_commit-koding.yml.pngbin302703 -> 86043 bytes
-rw-r--r--doc/user/project/img/koding_different-stack-on-mr-try.pngbin333649 -> 93404 bytes
-rw-r--r--doc/user/project/img/koding_edit-on-ide.pngbin330880 -> 90701 bytes
-rw-r--r--doc/user/project/img/koding_enable-koding.pngbin73499 -> 20303 bytes
-rw-r--r--doc/user/project/img/koding_landing.pngbin268455 -> 81010 bytes
-rw-r--r--doc/user/project/img/koding_open-gitlab-from-koding.pngbin32559 -> 10851 bytes
-rw-r--r--doc/user/project/img/koding_run-in-ide.pngbin65465 -> 22179 bytes
-rw-r--r--doc/user/project/img/koding_run-mr-in-ide.pngbin339759 -> 93780 bytes
-rw-r--r--doc/user/project/img/koding_set-up-ide.pngbin207481 -> 54062 bytes
-rw-r--r--doc/user/project/img/koding_stack-import.pngbin500352 -> 137608 bytes
-rw-r--r--doc/user/project/img/koding_start-build.pngbin105253 -> 27926 bytes
-rw-r--r--doc/user/project/img/labels_assign_label_in_new_issue.pngbin31126 -> 11636 bytes
-rw-r--r--doc/user/project/img/labels_assign_label_sidebar.pngbin31537 -> 11767 bytes
-rw-r--r--doc/user/project/img/labels_assign_label_sidebar_saved.pngbin28396 -> 9741 bytes
-rw-r--r--doc/user/project/img/labels_default.pngbin80403 -> 32030 bytes
-rw-r--r--doc/user/project/img/labels_description_tooltip.pngbin22585 -> 8538 bytes
-rw-r--r--doc/user/project/img/labels_filter.pngbin81536 -> 31931 bytes
-rw-r--r--doc/user/project/img/labels_filter_by_priority.pngbin60849 -> 23969 bytes
-rw-r--r--doc/user/project/img/labels_generate.pngbin31608 -> 13628 bytes
-rw-r--r--doc/user/project/img/labels_new_label.pngbin43265 -> 16787 bytes
-rw-r--r--doc/user/project/img/labels_new_label_on_the_fly.pngbin10416 -> 4625 bytes
-rw-r--r--doc/user/project/img/labels_new_label_on_the_fly_create.pngbin16151 -> 6389 bytes
-rw-r--r--doc/user/project/img/labels_prioritize.pngbin108751 -> 38185 bytes
-rw-r--r--doc/user/project/img/labels_subscribe.pngbin11536 -> 5336 bytes
-rw-r--r--doc/user/project/img/mitmproxy-docker.pngbin407004 -> 142591 bytes
-rw-r--r--doc/user/project/img/project_repository_settings.pngbin0 -> 35236 bytes
-rw-r--r--doc/user/project/img/project_settings_list.pngbin10788 -> 0 bytes
-rw-r--r--doc/user/project/img/protected_branches_choose_branch.pngbin20659 -> 7009 bytes
-rw-r--r--doc/user/project/img/protected_branches_delete.pngbin0 -> 21510 bytes
-rw-r--r--doc/user/project/img/protected_branches_devs_can_push.pngbin19312 -> 34888 bytes
-rw-r--r--doc/user/project/img/protected_branches_error_ui.pngbin37750 -> 13125 bytes
-rw-r--r--doc/user/project/img/protected_branches_list.pngbin16223 -> 6937 bytes
-rw-r--r--doc/user/project/img/protected_branches_matches.pngbin32145 -> 12028 bytes
-rw-r--r--doc/user/project/img/protected_branches_page.pngbin17839 -> 7205 bytes
-rw-r--r--doc/user/project/img/protected_tag_matches.pngbin0 -> 85305 bytes
-rw-r--r--doc/user/project/img/protected_tags_list.pngbin0 -> 24490 bytes
-rw-r--r--doc/user/project/img/protected_tags_page.pngbin0 -> 56112 bytes
-rw-r--r--doc/user/project/img/protected_tags_permissions_dropdown.pngbin0 -> 26514 bytes
-rw-r--r--doc/user/project/integrations/bamboo.md59
-rw-r--r--doc/user/project/integrations/bugzilla.md18
-rw-r--r--doc/user/project/integrations/emails_on_push.md20
-rw-r--r--doc/user/project/integrations/hipchat.md53
-rw-r--r--doc/user/project/integrations/img/emails_on_push_service.pngbin0 -> 28535 bytes
-rw-r--r--doc/user/project/integrations/img/jira_add_user_to_group.pngbin0 -> 24838 bytes
-rw-r--r--doc/user/project/integrations/img/jira_create_new_group.pngbin0 -> 19127 bytes
-rw-r--r--doc/user/project/integrations/img/jira_create_new_group_name.pngbin0 -> 5168 bytes
-rw-r--r--doc/user/project/integrations/img/jira_create_new_user.pngbin0 -> 12625 bytes
-rw-r--r--doc/user/project/integrations/img/jira_group_access.pngbin0 -> 19235 bytes
-rw-r--r--doc/user/project/integrations/img/jira_issue_reference.pngbin0 -> 18399 bytes
-rw-r--r--doc/user/project/integrations/img/jira_merge_request_close.pngbin0 -> 21172 bytes
-rw-r--r--doc/user/project/integrations/img/jira_project_name.pngbin0 -> 26685 bytes
-rw-r--r--doc/user/project/integrations/img/jira_project_settings.pngbin0 -> 32791 bytes
-rw-r--r--doc/user/project/integrations/img/jira_service.pngbin0 -> 37869 bytes
-rw-r--r--doc/user/project/integrations/img/jira_service_close_comment.pngbin0 -> 11893 bytes
-rw-r--r--doc/user/project/integrations/img/jira_service_close_issue.pngbin0 -> 30570 bytes
-rw-r--r--doc/user/project/integrations/img/jira_service_page.pngbin0 -> 83466 bytes
-rw-r--r--doc/user/project/integrations/img/jira_user_management_link.pngbin0 -> 23921 bytes
-rw-r--r--doc/user/project/integrations/img/jira_workflow_screenshot.pngbin0 -> 66685 bytes
-rw-r--r--doc/user/project/integrations/img/kubernetes_configuration.pngbin0 -> 113827 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_add_slash_command.pngbin0 -> 9265 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_bot_auth.pngbin0 -> 8676 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_bot_available_commands.pngbin0 -> 4647 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_config_help.pngbin0 -> 102890 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_configuration.pngbin0 -> 249592 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_console_integrations.pngbin0 -> 314642 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_gitlab_token.pngbin0 -> 3688 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_goto_console.pngbin0 -> 7754 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_slash_command_configuration.pngbin0 -> 24169 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_slash_command_token.pngbin0 -> 8624 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_team_integrations.pngbin0 -> 4766 bytes
-rw-r--r--doc/user/project/integrations/img/merge_request_performance.pngbin0 -> 60194 bytes
-rw-r--r--doc/user/project/integrations/img/microsoft_teams_configuration.pngbin0 -> 350592 bytes
-rw-r--r--doc/user/project/integrations/img/project_services.pngbin0 -> 25753 bytes
-rw-r--r--doc/user/project/integrations/img/prometheus_gcp_firewall_rule.pngbin0 -> 15247 bytes
-rw-r--r--doc/user/project/integrations/img/prometheus_gcp_node_name.pngbin0 -> 52622 bytes
-rw-r--r--doc/user/project/integrations/img/prometheus_service_configuration.pngbin0 -> 18100 bytes
-rw-r--r--doc/user/project/integrations/img/prometheus_yaml_deploy.pngbin0 -> 23567 bytes
-rw-r--r--doc/user/project/integrations/img/redmine_configuration.pngbin0 -> 10266 bytes
-rw-r--r--doc/user/project/integrations/img/services_templates_redmine_example.pngbin0 -> 8608 bytes
-rw-r--r--doc/user/project/integrations/img/slack_configuration.pngbin0 -> 229050 bytes
-rw-r--r--doc/user/project/integrations/img/slack_setup.pngbin0 -> 86314 bytes
-rwxr-xr-xdoc/user/project/integrations/img/webhook_logs.pngbin0 -> 24066 bytes
-rw-r--r--doc/user/project/integrations/img/webhooks_ssl.pngbin0 -> 27799 bytes
-rw-r--r--doc/user/project/integrations/index.md24
-rw-r--r--doc/user/project/integrations/irker.md50
-rw-r--r--doc/user/project/integrations/jira.md215
-rw-r--r--doc/user/project/integrations/kubernetes.md71
-rw-r--r--doc/user/project/integrations/mattermost.md45
-rw-r--r--doc/user/project/integrations/mattermost_slash_commands.md164
-rw-r--r--doc/user/project/integrations/microsoft_teams.md33
-rw-r--r--doc/user/project/integrations/mock_ci.md13
-rw-r--r--doc/user/project/integrations/project_services.md73
-rw-r--r--doc/user/project/integrations/prometheus.md208
-rw-r--r--doc/user/project/integrations/redmine.md23
-rw-r--r--doc/user/project/integrations/samples/prometheus.yml69
-rw-r--r--doc/user/project/integrations/services_templates.md26
-rw-r--r--doc/user/project/integrations/slack.md26
-rw-r--r--doc/user/project/integrations/slack_slash_commands.md23
-rw-r--r--doc/user/project/integrations/webhooks.md1066
-rw-r--r--doc/user/project/issue_board.md65
-rw-r--r--doc/user/project/issues/closing_issues.md59
-rw-r--r--doc/user/project/issues/confidential_issues.md68
-rw-r--r--doc/user/project/issues/create_new_issue.md38
-rw-r--r--doc/user/project/issues/crosslinking_issues.md63
-rw-r--r--doc/user/project/issues/due_dates.md39
-rwxr-xr-xdoc/user/project/issues/img/button_close_issue.pngbin0 -> 15508 bytes
-rw-r--r--doc/user/project/issues/img/close_issue_from_board.gifbin0 -> 109533 bytes
-rwxr-xr-xdoc/user/project/issues/img/closing_and_related_issues.pngbin0 -> 6395 bytes
-rwxr-xr-xdoc/user/project/issues/img/confidential_issues_create.pngbin0 -> 8185 bytes
-rwxr-xr-xdoc/user/project/issues/img/confidential_issues_index_page.pngbin0 -> 8349 bytes
-rwxr-xr-xdoc/user/project/issues/img/confidential_issues_issue_page.pngbin0 -> 14230 bytes
-rwxr-xr-xdoc/user/project/issues/img/confidential_issues_search_guest.pngbin0 -> 8593 bytes
-rwxr-xr-xdoc/user/project/issues/img/confidential_issues_search_master.pngbin0 -> 13228 bytes
-rwxr-xr-xdoc/user/project/issues/img/confidential_issues_system_notes.pngbin0 -> 2330 bytes
-rwxr-xr-xdoc/user/project/issues/img/due_dates_create.pngbin0 -> 6992 bytes
-rwxr-xr-xdoc/user/project/issues/img/due_dates_edit_sidebar.pngbin0 -> 1700 bytes
-rwxr-xr-xdoc/user/project/issues/img/due_dates_issues_index_page.pngbin0 -> 19302 bytes
-rwxr-xr-xdoc/user/project/issues/img/due_dates_todos.pngbin0 -> 4799 bytes
-rwxr-xr-xdoc/user/project/issues/img/issue_board.pngbin0 -> 58645 bytes
-rwxr-xr-xdoc/user/project/issues/img/issue_template.pngbin0 -> 28061 bytes
-rwxr-xr-xdoc/user/project/issues/img/issue_tracker.pngbin0 -> 37037 bytes
-rw-r--r--doc/user/project/issues/img/issues_main_view.pngbin0 -> 73751 bytes
-rw-r--r--doc/user/project/issues/img/issues_main_view_numbered.jpgbin0 -> 103249 bytes
-rwxr-xr-xdoc/user/project/issues/img/mention_in_issue.pngbin0 -> 3738 bytes
-rwxr-xr-xdoc/user/project/issues/img/mention_in_merge_request.pngbin0 -> 3944 bytes
-rwxr-xr-xdoc/user/project/issues/img/merge_request_closes_issue.pngbin0 -> 19423 bytes
-rwxr-xr-xdoc/user/project/issues/img/new_issue.pngbin0 -> 31727 bytes
-rwxr-xr-xdoc/user/project/issues/img/new_issue_from_issue_board.pngbin0 -> 137175 bytes
-rwxr-xr-xdoc/user/project/issues/img/new_issue_from_open_issue.pngbin0 -> 20628 bytes
-rwxr-xr-xdoc/user/project/issues/img/new_issue_from_projects_dashboard.pngbin0 -> 29865 bytes
-rwxr-xr-xdoc/user/project/issues/img/new_issue_from_tracker_list.pngbin0 -> 24345 bytes
-rw-r--r--doc/user/project/issues/index.md104
-rw-r--r--doc/user/project/issues/issues_functionalities.md176
-rw-r--r--doc/user/project/labels.md13
-rw-r--r--doc/user/project/merge_requests.md170
-rw-r--r--doc/user/project/merge_requests/img/cherry_pick_changes_commit.pngbin304098 -> 141744 bytes
-rw-r--r--doc/user/project/merge_requests/img/cherry_pick_changes_commit_modal.pngbin264883 -> 111488 bytes
-rw-r--r--doc/user/project/merge_requests/img/cherry_pick_changes_mr.pngbin212267 -> 93870 bytes
-rw-r--r--doc/user/project/merge_requests/img/cherry_pick_changes_mr_modal.pngbin186597 -> 86650 bytes
-rw-r--r--doc/user/project/merge_requests/img/commit_compare.pngbin65010 -> 33385 bytes
-rw-r--r--doc/user/project/merge_requests/img/conflict_section.pngbin247537 -> 72815 bytes
-rw-r--r--doc/user/project/merge_requests/img/discussion_view.pngbin292754 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/discussions_resolved.pngbin12840 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_conflict_editor.pngbin0 -> 50422 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_request_diff.pngbin69394 -> 26650 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_request_widget.pngbin32292 -> 11039 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_when_build_succeeds_enable.pngbin68769 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_when_build_succeeds_only_if_succeeds_msg.pngbin11136 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_when_build_succeeds_only_if_succeeds_settings.pngbin17552 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_when_build_succeeds_status.pngbin82655 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_enable.pngbin0 -> 60346 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_msg.pngbin0 -> 5251 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_settings.pngbin0 -> 25783 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_status.pngbin0 -> 69953 bytes
-rw-r--r--doc/user/project/merge_requests/img/resolve_comment_button.pngbin14075 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/resolve_discussion_button.pngbin18405 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/revert_changes_commit.pngbin233750 -> 95655 bytes
-rw-r--r--doc/user/project/merge_requests/img/revert_changes_commit_modal.pngbin205046 -> 88824 bytes
-rw-r--r--doc/user/project/merge_requests/img/revert_changes_mr.pngbin241051 -> 104972 bytes
-rw-r--r--doc/user/project/merge_requests/img/revert_changes_mr_modal.pngbin211022 -> 93536 bytes
-rw-r--r--doc/user/project/merge_requests/img/versions-compare.pngbin68722 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/versions-dropdown.pngbin60587 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/versions.pngbin171413 -> 55703 bytes
-rw-r--r--doc/user/project/merge_requests/img/versions_compare.pngbin0 -> 24886 bytes
-rw-r--r--doc/user/project/merge_requests/img/versions_dropdown.pngbin0 -> 21547 bytes
-rw-r--r--doc/user/project/merge_requests/img/versions_system_note.pngbin0 -> 7136 bytes
-rw-r--r--doc/user/project/merge_requests/img/wip_blocked_accept_button.pngbin32720 -> 18606 bytes
-rw-r--r--doc/user/project/merge_requests/img/wip_mark_as_wip.pngbin21640 -> 11396 bytes
-rw-r--r--doc/user/project/merge_requests/img/wip_unmark_as_wip.pngbin16606 -> 8565 bytes
-rw-r--r--doc/user/project/merge_requests/index.md169
-rw-r--r--doc/user/project/merge_requests/merge_request_discussion_resolution.md41
-rw-r--r--doc/user/project/merge_requests/merge_when_build_succeeds.md47
-rw-r--r--doc/user/project/merge_requests/merge_when_pipeline_succeeds.md47
-rw-r--r--doc/user/project/merge_requests/resolve_conflicts.md12
-rw-r--r--doc/user/project/merge_requests/versions.md31
-rw-r--r--doc/user/project/milestones/img/milestone_create.pngbin0 -> 40591 bytes
-rw-r--r--doc/user/project/milestones/img/milestone_group_create.pngbin0 -> 35526 bytes
-rw-r--r--doc/user/project/milestones/img/progress.pngbin0 -> 23491 bytes
-rw-r--r--doc/user/project/milestones/index.md54
-rw-r--r--doc/user/project/new_ci_build_permissions_model.md247
-rw-r--r--doc/user/project/pages/getting_started_part_four.md390
-rw-r--r--doc/user/project/pages/getting_started_part_one.md111
-rw-r--r--doc/user/project/pages/getting_started_part_three.md195
-rw-r--r--doc/user/project/pages/getting_started_part_two.md159
-rw-r--r--doc/user/project/pages/img/add_certificate_to_pages.pngbin0 -> 14608 bytes
-rw-r--r--doc/user/project/pages/img/choose_ci_template.pngbin0 -> 23532 bytes
-rw-r--r--doc/user/project/pages/img/dns_add_new_a_record_example_updated.pngbin0 -> 10578 bytes
-rw-r--r--doc/user/project/pages/img/dns_cname_record_example.pngbin0 -> 4983 bytes
-rw-r--r--doc/user/project/pages/img/pages_create_project.pngbin0 -> 6063 bytes
-rw-r--r--doc/user/project/pages/img/pages_create_user_page.pngbin0 -> 14435 bytes
-rw-r--r--doc/user/project/pages/img/pages_dns_details.pngbin0 -> 5351 bytes
-rw-r--r--doc/user/project/pages/img/pages_multiple_domains.pngbin0 -> 12936 bytes
-rw-r--r--doc/user/project/pages/img/pages_new_domain_button.pngbin0 -> 8763 bytes
-rw-r--r--doc/user/project/pages/img/pages_remove.pngbin0 -> 3810 bytes
-rw-r--r--doc/user/project/pages/img/pages_upload_cert.pngbin0 -> 22907 bytes
-rw-r--r--doc/user/project/pages/img/remove_fork_relashionship.pngbin0 -> 13642 bytes
-rw-r--r--doc/user/project/pages/img/setup_ci.pngbin0 -> 10032 bytes
-rw-r--r--doc/user/project/pages/index.md49
-rw-r--r--doc/user/project/pages/introduction.md447
-rw-r--r--doc/user/project/pipelines/img/job_artifacts_browser.pngbin0 -> 3771 bytes
-rw-r--r--doc/user/project/pipelines/img/job_artifacts_browser_button.pngbin0 -> 5534 bytes
-rw-r--r--doc/user/project/pipelines/img/job_artifacts_builds_page.pngbin0 -> 15191 bytes
-rw-r--r--doc/user/project/pipelines/img/job_artifacts_pipelines_page.pngbin0 -> 16550 bytes
-rw-r--r--doc/user/project/pipelines/img/job_latest_artifacts_browser.pngbin0 -> 10551 bytes
-rw-r--r--doc/user/project/pipelines/img/pipeline_schedules_list.pngbin0 -> 14665 bytes
-rw-r--r--doc/user/project/pipelines/img/pipeline_schedules_new_form.pngbin0 -> 49873 bytes
-rw-r--r--doc/user/project/pipelines/img/pipeline_schedules_ownership.pngbin0 -> 12043 bytes
-rw-r--r--doc/user/project/pipelines/img/pipelines_settings_badges.pngbin0 -> 21137 bytes
-rw-r--r--doc/user/project/pipelines/img/pipelines_settings_test_coverage.pngbin0 -> 2549 bytes
-rw-r--r--doc/user/project/pipelines/img/pipelines_test_coverage_build.pngbin0 -> 4481 bytes
-rw-r--r--doc/user/project/pipelines/img/pipelines_test_coverage_mr_widget.pngbin0 -> 6375 bytes
-rw-r--r--doc/user/project/pipelines/job_artifacts.md155
-rw-r--r--doc/user/project/pipelines/schedules.md82
-rw-r--r--doc/user/project/pipelines/settings.md129
-rw-r--r--doc/user/project/protected_branches.md34
-rw-r--r--doc/user/project/protected_tags.md60
-rw-r--r--doc/user/project/quick_actions.md39
-rw-r--r--doc/user/project/repository/branches/img/delete_merged_branches.pngbin0 -> 42891 bytes
-rw-r--r--doc/user/project/repository/branches/index.md17
-rw-r--r--doc/user/project/repository/img/web_editor_new_branch_dropdown.pngbin20436 -> 10386 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_new_branch_from_issue.pngbin0 -> 2720 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_new_branch_page.pngbin11245 -> 6034 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_new_directory_dialog.pngbin13339 -> 7323 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_new_directory_dropdown.pngbin20007 -> 9918 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_new_file_dropdown.pngbin20680 -> 10233 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_new_file_editor.pngbin66261 -> 38068 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_new_push_widget.pngbin7076 -> 3395 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_new_tag_dropdown.pngbin20080 -> 9796 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_new_tag_page.pngbin36610 -> 21835 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_start_new_merge_request.pngbin8596 -> 4060 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_template_dropdown_buttons.pngbin14131 -> 5634 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_template_dropdown_first_file.pngbin25748 -> 8846 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_template_dropdown_mit_license.pngbin85413 -> 30924 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_upload_file_dialog.pngbin21502 -> 12558 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_upload_file_dropdown.pngbin20651 -> 10291 bytes
-rw-r--r--doc/user/project/repository/web_editor.md14
-rw-r--r--doc/user/project/settings/img/import_export_download_export.pngbin85600 -> 24482 bytes
-rw-r--r--doc/user/project/settings/img/import_export_export_button.pngbin84637 -> 24122 bytes
-rw-r--r--doc/user/project/settings/img/import_export_mail_link.pngbin44012 -> 13496 bytes
-rw-r--r--doc/user/project/settings/img/import_export_new_project.pngbin43574 -> 13083 bytes
-rw-r--r--doc/user/project/settings/img/import_export_select_file.pngbin46292 -> 13713 bytes
-rw-r--r--doc/user/project/settings/img/settings_edit_button.pngbin19392 -> 6901 bytes
-rw-r--r--doc/user/project/settings/import_export.md24
-rw-r--r--doc/user/project/slash_commands.md32
-rw-r--r--doc/user/project/wiki/img/wiki_create_home_page.pngbin0 -> 12422 bytes
-rw-r--r--doc/user/project/wiki/img/wiki_create_new_page.pngbin0 -> 38105 bytes
-rw-r--r--doc/user/project/wiki/img/wiki_create_new_page_modal.pngbin0 -> 13189 bytes
-rw-r--r--doc/user/project/wiki/img/wiki_page_history.pngbin0 -> 26478 bytes
-rw-r--r--doc/user/project/wiki/img/wiki_sidebar.pngbin0 -> 7440 bytes
-rw-r--r--doc/user/project/wiki/index.md97
-rw-r--r--doc/user/search/img/issue_search_filter.pngbin0 -> 69559 bytes
-rwxr-xr-xdoc/user/search/img/issues_any_assignee.pngbin0 -> 90455 bytes
-rwxr-xr-xdoc/user/search/img/issues_assigned_to_you.pngbin0 -> 49079 bytes
-rwxr-xr-xdoc/user/search/img/issues_author.pngbin0 -> 55217 bytes
-rwxr-xr-xdoc/user/search/img/issues_mrs_shortcut.pngbin0 -> 34115 bytes
-rwxr-xr-xdoc/user/search/img/left_menu_bar.pngbin0 -> 37433 bytes
-rwxr-xr-xdoc/user/search/img/project_search.pngbin0 -> 41900 bytes
-rw-r--r--doc/user/search/img/search_history.gifbin0 -> 265970 bytes
-rwxr-xr-xdoc/user/search/img/search_issues_board.pngbin0 -> 82113 bytes
-rwxr-xr-xdoc/user/search/img/sort_projects.pngbin0 -> 59495 bytes
-rw-r--r--doc/user/search/index.md104
-rw-r--r--doc/user/snippets.md29
-rw-r--r--doc/web_hooks/ssl.pngbin39120 -> 0 bytes
-rw-r--r--doc/web_hooks/web_hooks.md957
-rw-r--r--doc/workflow/README.md20
-rw-r--r--doc/workflow/add-user/img/access_requests_management.pngbin15686 -> 11018 bytes
-rw-r--r--doc/workflow/add-user/img/add_new_user_to_project_settings.pngbin18149 -> 11046 bytes
-rw-r--r--doc/workflow/add-user/img/add_user_email_accept.pngbin22877 -> 16890 bytes
-rw-r--r--doc/workflow/add-user/img/add_user_email_ready.pngbin40207 -> 28171 bytes
-rw-r--r--doc/workflow/add-user/img/add_user_email_search.pngbin45798 -> 29628 bytes
-rw-r--r--doc/workflow/add-user/img/add_user_give_permissions.pngbin56380 -> 36619 bytes
-rw-r--r--doc/workflow/add-user/img/add_user_import_members_from_another_project.pngbin38778 -> 25343 bytes
-rw-r--r--doc/workflow/add-user/img/add_user_imported_members.pngbin37835 -> 25398 bytes
-rw-r--r--doc/workflow/add-user/img/add_user_list_members.pngbin24337 -> 16916 bytes
-rw-r--r--doc/workflow/add-user/img/add_user_members_menu.pngbin42224 -> 28994 bytes
-rw-r--r--doc/workflow/add-user/img/add_user_search_people.pngbin39844 -> 25368 bytes
-rw-r--r--doc/workflow/add-user/img/request_access_button.pngbin36588 -> 25281 bytes
-rw-r--r--doc/workflow/add-user/img/withdraw_access_request_button.pngbin37960 -> 26135 bytes
-rw-r--r--doc/workflow/award_emoji.md66
-rw-r--r--doc/workflow/award_emoji.pngbin9939 -> 5268 bytes
-rw-r--r--doc/workflow/ci_mr.pngbin29571 -> 12034 bytes
-rw-r--r--doc/workflow/close_issue_mr.pngbin82595 -> 42108 bytes
-rw-r--r--doc/workflow/environment_branches.pngbin20745 -> 12364 bytes
-rw-r--r--doc/workflow/forking/branch_select.pngbin27299 -> 15424 bytes
-rw-r--r--doc/workflow/forking/merge_request.pngbin31560 -> 16332 bytes
-rw-r--r--doc/workflow/four_stages.pngbin10003 -> 7124 bytes
-rw-r--r--doc/workflow/git_pull.pngbin94405 -> 28749 bytes
-rw-r--r--doc/workflow/gitdashflow.pngbin131491 -> 68177 bytes
-rw-r--r--doc/workflow/github_flow.pngbin10251 -> 6173 bytes
-rw-r--r--doc/workflow/gitlab_flow.md19
-rw-r--r--doc/workflow/gitlab_flow.pngbin70871 -> 47432 bytes
-rw-r--r--doc/workflow/good_commit.pngbin13131 -> 8742 bytes
-rw-r--r--doc/workflow/groups.md11
-rw-r--r--doc/workflow/groups/access_requests_management.pngbin15829 -> 11186 bytes
-rw-r--r--doc/workflow/groups/add_member_to_group.pngbin78060 -> 35724 bytes
-rw-r--r--doc/workflow/groups/group_dashboard.pngbin59446 -> 28155 bytes
-rw-r--r--doc/workflow/groups/group_with_two_projects.pngbin73101 -> 34462 bytes
-rw-r--r--doc/workflow/groups/max_access_level.pngbin74947 -> 34718 bytes
-rw-r--r--doc/workflow/groups/new_group_button.pngbin108482 -> 49708 bytes
-rw-r--r--doc/workflow/groups/new_group_form.pngbin58860 -> 114515 bytes
-rw-r--r--doc/workflow/groups/other_group_sees_shared_project.pngbin64447 -> 30182 bytes
-rw-r--r--doc/workflow/groups/override_access_level.pngbin90122 -> 40993 bytes
-rw-r--r--doc/workflow/groups/project_members_via_group.pngbin86260 -> 39532 bytes
-rw-r--r--doc/workflow/groups/request_access_button.pngbin49067 -> 35917 bytes
-rw-r--r--doc/workflow/groups/share_project_with_groups.pngbin65633 -> 30307 bytes
-rw-r--r--doc/workflow/groups/transfer_project.pngbin92115 -> 43502 bytes
-rw-r--r--doc/workflow/groups/withdraw_access_request_button.pngbin49941 -> 36413 bytes
-rw-r--r--doc/workflow/img/award_emoji_comment_awarded.pngbin64317 -> 0 bytes
-rw-r--r--doc/workflow/img/award_emoji_comment_picker.pngbin250861 -> 0 bytes
-rw-r--r--doc/workflow/img/award_emoji_select.pngbin49296 -> 0 bytes
-rw-r--r--doc/workflow/img/award_emoji_votes_least_popular.pngbin116715 -> 0 bytes
-rw-r--r--doc/workflow/img/award_emoji_votes_most_popular.pngbin108775 -> 0 bytes
-rw-r--r--doc/workflow/img/award_emoji_votes_sort_options.pngbin131659 -> 0 bytes
-rw-r--r--doc/workflow/img/file_finder_find_button.pngbin25458 -> 14567 bytes
-rw-r--r--doc/workflow/img/file_finder_find_file.pngbin35114 -> 19478 bytes
-rw-r--r--doc/workflow/img/forking_workflow_choose_namespace.pngbin59114 -> 26275 bytes
-rw-r--r--doc/workflow/img/forking_workflow_fork_button.pngbin20750 -> 12973 bytes
-rw-r--r--doc/workflow/img/forking_workflow_path_taken_error.pngbin17978 -> 10103 bytes
-rw-r--r--doc/workflow/img/new_branch_from_issue.pngbin54607 -> 33584 bytes
-rw-r--r--doc/workflow/img/notification_global_settings.pngbin0 -> 37542 bytes
-rw-r--r--doc/workflow/img/notification_group_settings.pngbin0 -> 171784 bytes
-rw-r--r--doc/workflow/img/notification_project_settings.pngbin0 -> 167548 bytes
-rw-r--r--doc/workflow/img/todo_list_item.pngbin58912 -> 18777 bytes
-rw-r--r--doc/workflow/img/todos_add_todo_sidebar.pngbin120265 -> 42360 bytes
-rw-r--r--doc/workflow/img/todos_icon.pngbin3843 -> 4910 bytes
-rw-r--r--doc/workflow/img/todos_index.pngbin152040 -> 98239 bytes
-rw-r--r--doc/workflow/img/todos_mark_done_sidebar.pngbin121303 -> 42317 bytes
-rw-r--r--doc/workflow/importing/README.md2
-rw-r--r--doc/workflow/importing/bitbucket_importer/bitbucket_import_grant_access.pngbin30083 -> 0 bytes
-rw-r--r--doc/workflow/importing/bitbucket_importer/bitbucket_import_new_project.pngbin16502 -> 0 bytes
-rw-r--r--doc/workflow/importing/bitbucket_importer/bitbucket_import_select_bitbucket.pngbin46606 -> 0 bytes
-rw-r--r--doc/workflow/importing/bitbucket_importer/bitbucket_import_select_project.pngbin15288 -> 0 bytes
-rw-r--r--doc/workflow/importing/fogbugz_importer/fogbugz_import_finished.pngbin30266 -> 17744 bytes
-rw-r--r--doc/workflow/importing/fogbugz_importer/fogbugz_import_login.pngbin20797 -> 13751 bytes
-rw-r--r--doc/workflow/importing/fogbugz_importer/fogbugz_import_select_fogbogz.pngbin20526 -> 12289 bytes
-rw-r--r--doc/workflow/importing/fogbugz_importer/fogbugz_import_select_project.pngbin34836 -> 20905 bytes
-rw-r--r--doc/workflow/importing/fogbugz_importer/fogbugz_import_user_map.pngbin77208 -> 51238 bytes
-rw-r--r--doc/workflow/importing/gitlab_importer/importer.pngbin18366 -> 12864 bytes
-rw-r--r--doc/workflow/importing/gitlab_importer/new_project_page.pngbin33589 -> 21251 bytes
-rw-r--r--doc/workflow/importing/img/bitbucket_import_grant_access.pngbin0 -> 7248 bytes
-rw-r--r--doc/workflow/importing/img/bitbucket_import_new_project.pngbin0 -> 1316 bytes
-rw-r--r--doc/workflow/importing/img/bitbucket_import_select_project.pngbin0 -> 8688 bytes
-rw-r--r--doc/workflow/importing/img/import_projects_from_gitea_new_import.pngbin0 -> 15561 bytes
-rw-r--r--doc/workflow/importing/img/import_projects_from_github_importer.pngbin65288 -> 17953 bytes
-rw-r--r--doc/workflow/importing/img/import_projects_from_github_new_project_page.pngbin24911 -> 0 bytes
-rw-r--r--doc/workflow/importing/img/import_projects_from_github_select_auth_method.pngbin42043 -> 17612 bytes
-rw-r--r--doc/workflow/importing/img/import_projects_from_new_project_page.pngbin0 -> 36821 bytes
-rw-r--r--doc/workflow/importing/import_projects_from_bitbucket.md62
-rw-r--r--doc/workflow/importing/import_projects_from_gitea.md77
-rw-r--r--doc/workflow/importing/import_projects_from_github.md22
-rw-r--r--doc/workflow/importing/import_projects_from_gitlab_com.md3
-rw-r--r--doc/workflow/importing/migrating_from_svn.md108
-rw-r--r--doc/workflow/lfs/lfs_administration.md10
-rw-r--r--doc/workflow/lfs/manage_large_binaries_with_git_lfs.md26
-rw-r--r--doc/workflow/merge_commits.pngbin22181 -> 7564 bytes
-rw-r--r--doc/workflow/merge_request.pngbin98070 -> 47240 bytes
-rw-r--r--doc/workflow/merge_when_build_succeeds.md2
-rw-r--r--doc/workflow/messy_flow.pngbin19314 -> 11665 bytes
-rw-r--r--doc/workflow/milestones.md14
-rw-r--r--doc/workflow/milestones/form.pngbin84872 -> 0 bytes
-rw-r--r--doc/workflow/milestones/group_form.pngbin74429 -> 0 bytes
-rw-r--r--doc/workflow/mr_inline_comments.pngbin117313 -> 52519 bytes
-rw-r--r--doc/workflow/notifications.md12
-rw-r--r--doc/workflow/notifications/settings.pngbin59256 -> 0 bytes
-rw-r--r--doc/workflow/production_branch.pngbin10946 -> 7264 bytes
-rw-r--r--doc/workflow/project_features.md2
-rw-r--r--doc/workflow/rebase.pngbin68976 -> 29009 bytes
-rw-r--r--doc/workflow/release_branches.pngbin22163 -> 12746 bytes
-rw-r--r--doc/workflow/releases/new_tag.pngbin87330 -> 42456 bytes
-rw-r--r--doc/workflow/releases/tags.pngbin93016 -> 44666 bytes
-rw-r--r--doc/workflow/remove_checkbox.pngbin12339 -> 6904 bytes
-rw-r--r--doc/workflow/shortcuts.md16
-rw-r--r--doc/workflow/time-tracking/time-tracking-example.pngbin0 -> 48350 bytes
-rw-r--r--doc/workflow/time-tracking/time-tracking-sidebar.pngbin0 -> 19467 bytes
-rw-r--r--doc/workflow/time_tracking.md73
-rw-r--r--doc/workflow/todos.md41
1189 files changed, 35918 insertions, 10340 deletions
diff --git a/doc/README.md b/doc/README.md
index 9017b143260..ab8ea192a26 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -1,61 +1,188 @@
-# Documentation
+# GitLab Community Edition
-## User documentation
+[GitLab](https://about.gitlab.com/) is a Git-based fully featured platform
+for software development.
-- [Account Security](user/account/security.md) Securing your account via two-factor authentication, etc.
-- [API](api/README.md) Automate GitLab via a simple and powerful API.
-- [CI/CD](ci/README.md) GitLab Continuous Integration (CI) and Continuous Delivery (CD) getting started, `.gitlab-ci.yml` options, and examples.
-- [GitLab as OAuth2 authentication service provider](integration/oauth_provider.md). It allows you to login to other applications from GitLab.
-- [Container Registry](user/project/container_registry.md) Learn how to use GitLab Container Registry.
-- [GitLab Basics](gitlab-basics/README.md) Find step by step how to start working on your commandline and on GitLab.
-- [Importing to GitLab](workflow/importing/README.md).
+**GitLab Community Edition (CE)** is an opensource product, self-hosted, free to use.
+All [GitLab products](https://about.gitlab.com/products/) contain the features
+available in GitLab CE. Premium features are available in
+[GitLab Enterprise Edition (EE)](https://about.gitlab.com/gitlab-ee/).
+
+----
+
+Shortcuts to GitLab's most visited docs:
+
+| [GitLab CI](ci/README.md) | Other |
+| :----- | :----- |
+| [Quick start guide](ci/quick_start/README.md) | [API](api/README.md) |
+| [Configuring `.gitlab-ci.yml`](ci/yaml/README.md) | [SSH authentication](ssh/README.md) |
+| [Using Docker images](ci/docker/using_docker_images.md) | [GitLab Pages](user/project/pages/index.md) |
+
+## Getting started with GitLab
+
+- [GitLab Basics](gitlab-basics/README.md): Start working on your command line and on GitLab.
+- [GitLab Workflow](workflow/README.md): Enhance your workflow with the best of GitLab Workflow.
+ - See also [GitLab Workflow - an overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/).
+- [GitLab Markdown](user/markdown.md): GitLab's advanced formatting system (GitLab Flavored Markdown).
+- [GitLab Quick Actions](user/project/quick_actions.md): Textual shortcuts for common actions on issues or merge requests that are usually done by clicking buttons or dropdowns in GitLab's UI.
+
+### User account
+
+- [Authentication](topics/authentication/index.md): Account security with two-factor authentication, setup your ssh keys and deploy keys for secure access to your projects.
+- [Profile settings](profile/README.md): Manage your profile settings, two factor authentication and more.
+- [User permissions](user/permissions.md): Learn what each role in a project (external/guest/reporter/developer/master/owner) can do.
+
+### Projects and groups
+
+- [Create a project](gitlab-basics/create-project.md)
+- [Fork a project](gitlab-basics/fork-project.md)
- [Importing and exporting projects between instances](user/project/settings/import_export.md).
-- [Markdown](user/markdown.md) GitLab's advanced formatting system.
-- [Migrating from SVN](workflow/importing/migrating_from_svn.md) Convert a SVN repository to Git and GitLab.
-- [Permissions](user/permissions.md) Learn what each role in a project (external/guest/reporter/developer/master/owner) can do.
-- [Profile Settings](profile/README.md)
-- [Project Services](project_services/project_services.md) Integrate a project with external services, such as CI and chat.
-- [Public access](public_access/public_access.md) Learn how you can allow public and internal access to projects.
-- [SSH](ssh/README.md) Setup your ssh keys and deploy keys for secure access to your projects.
-- [Webhooks](web_hooks/web_hooks.md) Let GitLab notify you when new code has been pushed to your project.
-- [Workflow](workflow/README.md) Using GitLab functionality and importing projects from GitHub and SVN.
-- [University](university/README.md) Learn Git and GitLab through videos and courses.
+- [Project access](public_access/public_access.md): Setting up your project's visibility to public, internal, or private.
+- [Groups](workflow/groups.md): Organize your projects in groups.
+ - [Create a group](gitlab-basics/create-group.md)
+ - [GitLab Subgroups](user/group/subgroups/index.md)
+- [Search through GitLab](user/search/index.md): Search for issues, merge requests, projects, groups, todos, and issues in Issue Boards.
+- [Snippets](user/snippets.md): Snippets allow you to create little bits of code.
+- [Wikis](user/project/wiki/index.md): Enhance your repository documentation with built-in wikis.
+- [GitLab Pages](user/project/pages/index.md): Build, test, and deploy your static website with GitLab Pages.
+
+### Repository
+
+Manage files and branches from the UI (user interface):
+
+- Files
+ - [Create a file](user/project/repository/web_editor.md#create-a-file)
+ - [Upload a file](user/project/repository/web_editor.md#upload-a-file)
+ - [File templates](user/project/repository/web_editor.md#template-dropdowns)
+ - [Create a directory](user/project/repository/web_editor.md#create-a-directory)
+ - [Start a merge request](user/project/repository/web_editor.md#tips) (when committing via UI)
+- Branches
+ - [Create a branch](user/project/repository/web_editor.md#create-a-new-branch)
+ - [Protected branches](user/project/protected_branches.md#protected-branches)
+ - [Delete merged branches](user/project/repository/branches/index.md#delete-merged-branches)
+
+### Issues and Merge Requests (MRs)
+
+- [Discussions](user/discussions/index.md) Threads, comments, and resolvable discussions in issues, commits, and merge requests.
+- [Issues](user/project/issues/index.md)
+- [Issue Board](user/project/issue_board.md)
+- [Issues and merge requests templates](user/project/description_templates.md): Create templates for submitting new issues and merge requests.
+- [Labels](user/project/labels.md): Categorize your issues or merge requests based on descriptive titles.
+- [Merge Requests](user/project/merge_requests/index.md)
+ - [Work In Progress Merge Requests](user/project/merge_requests/work_in_progress_merge_requests.md)
+ - [Merge Request discussion resolution](user/discussions/index.md#moving-a-single-discussion-to-a-new-issue): Resolve discussions, move discussions in a merge request to an issue, only allow merge requests to be merged if all discussions are resolved.
+ - [Checkout merge requests locally](user/project/merge_requests/index.md#checkout-merge-requests-locally)
+ - [Cherry-pick](user/project/merge_requests/cherry_pick_changes.md)
+- [Milestones](user/project/milestones/index.md): Organize issues and merge requests into a cohesive group, optionally setting a due date.
+- [Todos](workflow/todos.md): A chronological list of to-dos that are waiting for your input, all in a simple dashboard.
+
+### Git and GitLab
+
+- [Git](topics/git/index.md): Getting started with Git, branching strategies, Git LFS, advanced use.
+- [Git cheatsheet](https://gitlab.com/gitlab-com/marketing/raw/master/design/print/git-cheatsheet/print-pdf/git-cheatsheet.pdf): Download a PDF describing the most used Git operations.
+- [GitLab Flow](workflow/gitlab_flow.md): explore the best of Git with the GitLab Flow strategy.
+
+### Migrate and import your projects from other platforms
+
+- [Importing to GitLab](workflow/importing/README.md): Import your projects from GitHub, Bitbucket, GitLab.com, FogBugz and SVN into GitLab.
+- [Migrating from SVN](workflow/importing/migrating_from_svn.md): Convert a SVN repository to Git and GitLab.
+
+### Continuous Integration, Delivery, and Deployment
+
+- [GitLab CI](ci/README.md): Explore the features and capabilities of Continuous Integration, Continuous Delivery, and Continuous Deployment with GitLab.
+ - [Auto Deploy](ci/autodeploy/index.md): Configure GitLab CI for the deployment of your application.
+ - [Review Apps](ci/review_apps/index.md): Preview changes to your app right from a merge request.
+- [GitLab Cycle Analytics](user/project/cycle_analytics.md): Cycle Analytics measures the time it takes to go from an [idea to production](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab) for each project you have.
+- [GitLab Container Registry](user/project/container_registry.md): Learn how to use GitLab's built-in Container Registry.
+
+### Automation
+
+- [API](api/README.md): Automate GitLab via a simple and powerful API.
+- [GitLab Webhooks](user/project/integrations/webhooks.md): Let GitLab notify you when new code has been pushed to your project.
+
+### Integrations
+
+- [Project Services](user/project/integrations/project_services.md): Integrate a project with external services, such as CI and chat.
+- [GitLab Integration](integration/README.md): Integrate with multiple third-party services with GitLab to allow external issue trackers and external authentication.
+
+----
## Administrator documentation
-- [Access restrictions](user/admin_area/settings/visibility_and_access_controls.md#enabled-git-access-protocols) Define which Git access protocols can be used to talk to GitLab
-- [Authentication/Authorization](administration/auth/README.md) Configure
- external authentication with LDAP, SAML, CAS and additional Omniauth providers.
-- [Custom Git hooks](administration/custom_hooks.md) Custom Git hooks (on the filesystem) for when webhooks aren't enough.
-- [Install](install/README.md) Requirements, directory structures and installation from source.
-- [Restart GitLab](administration/restart_gitlab.md) Learn how to restart GitLab and its components.
-- [Integration](integration/README.md) How to integrate with systems such as JIRA, Redmine, Twitter.
-- [Issue closing pattern](administration/issue_closing_pattern.md) Customize how to close an issue from commit messages.
-- [Koding](administration/integration/koding.md) Set up Koding to use with GitLab.
-- [Libravatar](customization/libravatar.md) Use Libravatar instead of Gravatar for user avatars.
-- [Log system](administration/logs.md) Log system.
-- [Environment Variables](administration/environment_variables.md) to configure GitLab.
-- [Operations](operations/README.md) Keeping GitLab up and running.
-- [Raketasks](raketasks/README.md) Backups, maintenance, automatic webhook setup and the importing of projects.
-- [Repository checks](administration/repository_checks.md) Periodic Git repository checks.
-- [Repository storages](administration/repository_storages.md) Manage the paths used to store repositories.
-- [Security](security/README.md) Learn what you can do to further secure your GitLab instance.
-- [System hooks](system_hooks/system_hooks.md) Notifications when users, projects and keys are changed.
-- [Update](update/README.md) Update guides to upgrade your installation.
-- [Welcome message](customization/welcome_message.md) Add a custom welcome message to the sign-in page.
-- [Reply by email](incoming_email/README.md) Allow users to comment on issues and merge requests by replying to notification emails.
-- [Migrate GitLab CI to CE/EE](migrate_ci_to_ce/README.md) Follow this guide to migrate your existing GitLab CI data to GitLab CE/EE.
-- [Git LFS configuration](workflow/lfs/lfs_administration.md)
-- [Housekeeping](administration/housekeeping.md) Keep your Git repository tidy and fast.
-- [GitLab Performance Monitoring](monitoring/performance/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics.
-- [Monitoring uptime](monitoring/health_check.md) Check the server status using the health check endpoint.
-- [Debugging Tips](administration/troubleshooting/debug.md) Tips to debug problems when things go wrong
-- [Sidekiq Troubleshooting](administration/troubleshooting/sidekiq.md) Debug when Sidekiq appears hung and is not processing jobs.
-- [High Availability](administration/high_availability/README.md) Configure multiple servers for scaling or high availability.
-- [Container Registry](administration/container_registry.md) Configure Docker Registry with GitLab.
-- [Multiple mountpoints for the repositories storage](administration/repository_storages.md) Define multiple repository storage paths to distribute the storage load.
+Learn how to administer your GitLab instance. Regular users don't
+have access to GitLab administration tools and settings.
+
+### Install, update, upgrade, migrate
+
+- [Install](install/README.md): Requirements, directory structures and installation from source.
+- [Mattermost](https://docs.gitlab.com/omnibus/gitlab-mattermost/): Integrate [Mattermost](https://about.mattermost.com/) with your GitLab installation.
+- [Migrate GitLab CI to CE/EE](migrate_ci_to_ce/README.md): If you have an old GitLab installation (older than 8.0), follow this guide to migrate your existing GitLab CI data to GitLab CE/EE.
+- [Restart GitLab](administration/restart_gitlab.md): Learn how to restart GitLab and its components.
+- [Update](update/README.md): Update guides to upgrade your installation.
+
+### User permissions
+
+- [Access restrictions](user/admin_area/settings/visibility_and_access_controls.md#enabled-git-access-protocols): Define which Git access protocols can be used to talk to GitLab
+- [Authentication/Authorization](topics/authentication/index.md#gitlab-administrators): Enforce 2FA, configure external authentication with LDAP, SAML, CAS and additional Omniauth providers.
+
+### GitLab admins' superpowers
+
+- [Container Registry](administration/container_registry.md): Configure Docker Registry with GitLab.
+- [Custom Git hooks](administration/custom_hooks.md): Custom Git hooks (on the filesystem) for when webhooks aren't enough.
+- [Git LFS configuration](workflow/lfs/lfs_administration.md): Learn how to use LFS under GitLab.
+- [GitLab Pages configuration](administration/pages/index.md): Configure GitLab Pages.
+- [High Availability](administration/high_availability/README.md): Configure multiple servers for scaling or high availability.
+- [User cohorts](user/admin_area/user_cohorts.md) View user activity over time.
+- [Web terminals](administration/integration/terminal.md): Provide terminal access to environments from within GitLab.
+- GitLab CI
+ - [CI admin settings](user/admin_area/settings/continuous_integration.md): Define max artifacts size and expiration time.
+
+### Integrations
+
+- [Integrations](integration/README.md): How to integrate with systems such as JIRA, Redmine, Twitter.
+- [Koding](administration/integration/koding.md): Set up Koding to use with GitLab.
+- [Mattermost](user/project/integrations/mattermost.md): Set up GitLab with Mattermost.
+
+### Monitoring
+
+- [GitLab performance monitoring with InfluxDB](administration/monitoring/performance/introduction.md): Configure GitLab and InfluxDB for measuring performance metrics.
+- [GitLab performance monitoring with Prometheus](administration/monitoring/prometheus/index.md): Configure GitLab and Prometheus for measuring performance metrics.
+- [Monitoring uptime](user/admin_area/monitoring/health_check.md): Check the server status using the health check endpoint.
+
+### Performance
+
+- [Housekeeping](administration/housekeeping.md): Keep your Git repository tidy and fast.
+- [Operations](administration/operations.md): Keeping GitLab up and running.
+- [Polling](administration/polling.md): Configure how often the GitLab UI polls for updates.
+- [Request Profiling](administration/monitoring/performance/request_profiling.md): Get a detailed profile on slow requests.
+
+### Customization
+
+- [Adjust your instance's timezone](workflow/timezone.md): Customize the default time zone of GitLab.
+- [Environment variables](administration/environment_variables.md): Supported environment variables that can be used to override their defaults values in order to configure GitLab.
+- [Header logo](customization/branded_page_and_email_header.md): Change the logo on the overall page and email header.
+- [Issue closing pattern](administration/issue_closing_pattern.md): Customize how to close an issue from commit messages.
+- [Libravatar](customization/libravatar.md): Use Libravatar instead of Gravatar for user avatars.
+- [Welcome message](customization/welcome_message.md): Add a custom welcome message to the sign-in page.
+
+### Admin tools
+
+- [Raketasks](raketasks/README.md): Backups, maintenance, automatic webhook setup and the importing of projects.
+ - [Backup and restore](raketasks/backup_restore.md): Backup and restore your GitLab instance.
+- [Reply by email](administration/reply_by_email.md): Allow users to comment on issues and merge requests by replying to notification emails.
+- [Repository checks](administration/repository_checks.md): Periodic Git repository checks.
+- [Repository storage paths](administration/repository_storage_paths.md): Manage the paths used to store repositories.
+- [Security](security/README.md): Learn what you can do to further secure your GitLab instance.
+- [System hooks](system_hooks/system_hooks.md): Notifications when users, projects and keys are changed.
+
+### Troubleshooting
+
+- [Debugging tips](administration/troubleshooting/debug.md): Tips to debug problems when things go wrong
+- [Log system](administration/logs.md): Where to look for logs.
+- [Sidekiq Troubleshooting](administration/troubleshooting/sidekiq.md): Debug when Sidekiq appears hung and is not processing jobs.
## Contributor documentation
-- [Development](development/README.md) All styleguides and explanations how to contribute.
-- [Legal](legal/README.md) Contributor license agreements.
+- [Development](development/README.md): All styleguides and explanations how to contribute.
+- [Legal](legal/README.md): Contributor license agreements.
+- [Writing documentation](development/writing_documentation.md): Contributing to GitLab Docs.
diff --git a/doc/administration/auth/README.md b/doc/administration/auth/README.md
index 07e548aaabe..13bd501e397 100644
--- a/doc/administration/auth/README.md
+++ b/doc/administration/auth/README.md
@@ -6,6 +6,7 @@ providers.
- [LDAP](ldap.md) Includes Active Directory, Apple Open Directory, Open LDAP,
and 389 Server
- [OmniAuth](../../integration/omniauth.md) Sign in via Twitter, GitHub, GitLab.com, Google,
- Bitbucket, Facebook, Shibboleth, Crowd and Azure
-- [SAML](../../integration/saml.md) Configure GitLab as a SAML 2.0 Service Provider
+ Bitbucket, Facebook, Shibboleth, Crowd, Azure and Authentiq ID
- [CAS](../../integration/cas.md) Configure GitLab to sign in using CAS
+- [SAML](../../integration/saml.md) Configure GitLab as a SAML 2.0 Service Provider
+- [Okta](okta.md) Configure GitLab to sign in using Okta
diff --git a/doc/administration/auth/authentiq.md b/doc/administration/auth/authentiq.md
new file mode 100644
index 00000000000..fb1a16b0f96
--- /dev/null
+++ b/doc/administration/auth/authentiq.md
@@ -0,0 +1,69 @@
+# Authentiq OmniAuth Provider
+
+To enable the Authentiq OmniAuth provider for passwordless authentication you must register an application with Authentiq.
+
+Authentiq will generate a Client ID and the accompanying Client Secret for you to use.
+
+1. Get your Client credentials (Client ID and Client Secret) at [Authentiq](https://www.authentiq.com/register).
+
+2. On your GitLab server, open the configuration file:
+
+ For omnibus installation
+ ```sh
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
+
+ For installations from source:
+
+ ```sh
+ sudo -u git -H editor /home/git/gitlab/config/gitlab.yml
+ ```
+
+3. See [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration) for initial settings to enable single sign-on and add Authentiq as an OAuth provider.
+
+4. Add the provider configuration for Authentiq:
+
+ For Omnibus packages:
+
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ "name" => "authentiq",
+ "app_id" => "YOUR_CLIENT_ID",
+ "app_secret" => "YOUR_CLIENT_SECRET",
+ "args" => {
+ scope: 'aq:name email~rs aq:push'
+ }
+ }
+ ]
+ ```
+
+ For installations from source:
+
+ ```yaml
+ - { name: 'authentiq',
+ app_id: 'YOUR_CLIENT_ID',
+ app_secret: 'YOUR_CLIENT_SECRET',
+ args: {
+ scope: 'aq:name email~rs aq:push'
+ }
+ }
+ ```
+
+
+5. The `scope` is set to request the user's name, email (required and signed), and permission to send push notifications to sign in on subsequent visits.
+See [OmniAuth Authentiq strategy](https://github.com/AuthentiqID/omniauth-authentiq#scopes-and-redirect-uri-configuration) for more information on scopes and modifiers.
+
+6. Change `YOUR_CLIENT_ID` and `YOUR_CLIENT_SECRET` to the Client credentials you received in step 1.
+
+7. Save the configuration file.
+
+8. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../restart_gitlab.md#installations-from-source)
+ for the changes to take effect if you installed GitLab via Omnibus or from source respectively.
+
+On the sign in page there should now be an Authentiq icon below the regular sign in form. Click the icon to begin the authentication process.
+
+- If the user has the Authentiq ID app installed in their iOS or Android device, they can scan the QR code, decide what personal details to share and sign in to your GitLab installation.
+- If not they will be prompted to download the app and then follow the procedure above.
+
+If everything goes right, the user will be returned to GitLab and will be signed in. \ No newline at end of file
diff --git a/doc/administration/auth/crowd.md b/doc/administration/auth/crowd.md
new file mode 100644
index 00000000000..2c289c67a6d
--- /dev/null
+++ b/doc/administration/auth/crowd.md
@@ -0,0 +1,68 @@
+# Atlassian Crowd OmniAuth Provider
+
+## Configure a new Crowd application
+
+1. Choose 'Applications' in the top menu, then 'Add application'.
+1. Go through the 'Add application' steps, entering the appropriate details.
+ The screenshot below shows an example configuration.
+
+ ![Example Crowd application configuration](img/crowd_application.png)
+
+## Configure GitLab
+
+1. On your GitLab server, open the configuration file.
+
+ **Omnibus:**
+
+ ```sh
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
+
+ **Source:**
+
+ ```sh
+ cd /home/git/gitlab
+
+ sudo -u git -H editor config/gitlab.yml
+ ```
+
+1. See [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration)
+ for initial settings.
+
+1. Add the provider configuration:
+
+ **Omnibus:**
+
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ "name" => "crowd",
+ "args" => {
+ "crowd_server_url" => "CROWD_SERVER_URL",
+ "application_name" => "YOUR_APP_NAME",
+ "application_password" => "YOUR_APP_PASSWORD"
+ }
+ }
+ ]
+ ```
+
+ **Source:**
+
+ ```
+ - { name: 'crowd',
+ args: {
+ crowd_server_url: 'CROWD_SERVER_URL',
+ application_name: 'YOUR_APP_NAME',
+ application_password: 'YOUR_APP_PASSWORD' } }
+ ```
+1. Change `CROWD_SERVER_URL` to the URL of your Crowd server.
+1. Change `YOUR_APP_NAME` to the application name from Crowd applications page.
+1. Change `YOUR_APP_PASSWORD` to the application password you've set.
+1. Save the configuration file.
+1. [Reconfigure][] or [restart][] for the changes to take effect if you
+ installed GitLab via Omnibus or from source respectively.
+
+On the sign in page there should now be a Crowd tab in the sign in form.
+
+[reconfigure]: ../restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart]: ../restart_gitlab.md#installations-from-source
diff --git a/doc/administration/auth/img/crowd_application.png b/doc/administration/auth/img/crowd_application.png
new file mode 100644
index 00000000000..7deea9dac8e
--- /dev/null
+++ b/doc/administration/auth/img/crowd_application.png
Binary files differ
diff --git a/doc/administration/auth/img/okta_admin_panel.png b/doc/administration/auth/img/okta_admin_panel.png
new file mode 100644
index 00000000000..12e21956715
--- /dev/null
+++ b/doc/administration/auth/img/okta_admin_panel.png
Binary files differ
diff --git a/doc/administration/auth/img/okta_saml_settings.png b/doc/administration/auth/img/okta_saml_settings.png
new file mode 100644
index 00000000000..ee275ece369
--- /dev/null
+++ b/doc/administration/auth/img/okta_saml_settings.png
Binary files differ
diff --git a/doc/administration/auth/ldap.md b/doc/administration/auth/ldap.md
index bf7814875bf..725fc1f6076 100644
--- a/doc/administration/auth/ldap.md
+++ b/doc/administration/auth/ldap.md
@@ -35,6 +35,10 @@ of one hour.
To enable LDAP integration you need to add your LDAP server settings in
`/etc/gitlab/gitlab.rb` or `/home/git/gitlab/config/gitlab.yml`.
+There is a Rake task to check LDAP configuration. After configuring LDAP
+using the documentation below, see [LDAP check Rake task](../raketasks/check.md#ldap-check)
+for information on the LDAP check Rake task.
+
>**Note**: In GitLab EE, you can configure multiple LDAP servers to connect to
one GitLab server.
@@ -62,10 +66,14 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
# Example: 'Paris' or 'Acme, Ltd.'
label: 'LDAP'
+ # Example: 'ldap.mydomain.com'
host: '_your_ldap_server'
+ # This port is an example, it is sometimes different but it is always an integer and not a string
port: 389
- uid: 'sAMAccountName'
+ uid: 'sAMAccountName' # This should be the attribute, not the value that maps to uid.
method: 'plain' # "tls" or "ssl" or "plain"
+
+ # Examples: 'america\\momo' or 'CN=Gitlab Git,CN=Users,DC=mydomain,DC=com'
bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
password: '_the_password_of_the_bind_user'
@@ -97,7 +105,7 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
# Base where we can search for users
#
- # Ex. ou=People,dc=gitlab,dc=example
+ # Ex. 'ou=People,dc=gitlab,dc=example' or 'DC=mydomain,DC=com'
#
base: ''
@@ -108,6 +116,9 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
#
# Note: GitLab does not support omniauth-ldap's custom filter syntax.
#
+ # Below an example for get only specific users
+ # Example: '(&(objectclass=user)(|(samaccountname=momo)(samaccountname=toto)))'
+ #
user_filter: ''
# LDAP attributes that GitLab will use to create an account for the LDAP user.
@@ -217,7 +228,7 @@ Tip: If you want to limit access to the nested members of an Active Directory
group you can use the following syntax:
```
-(memberOf:1.2.840.113556.1.4.1941:=CN=My Group,DC=Example,DC=com)
+(memberOf=CN=My Group,DC=Example,DC=com)
```
Please note that GitLab does not support the custom filter syntax used by
@@ -253,6 +264,24 @@ the LDAP server's SSL certificate is performed.
## Troubleshooting
+### Debug LDAP user filter with ldapsearch
+
+This example uses ldapsearch and assumes you are using ActiveDirectory. The
+following query returns the login names of the users that will be allowed to
+log in to GitLab if you configure your own user_filter.
+
+```
+ldapsearch -H ldaps://$host:$port -D "$bind_dn" -y bind_dn_password.txt -b "$base" "$user_filter" sAMAccountName
+```
+
+- Variables beginning with a `$` refer to a variable from the LDAP section of
+ your configuration file.
+- Replace ldaps:// with ldap:// if you are using the plain authentication method.
+ Port `389` is the default `ldap://` port and `636` is the default `ldaps://`
+ port.
+- We are assuming the password for the bind_dn user is in bind_dn_password.txt.
+
+
### Invalid credentials when logging in
- Make sure the user you are binding with has enough permissions to read the user's
@@ -276,8 +305,11 @@ LDAP server please double-check the LDAP `port` and `method` settings used by
GitLab. Common combinations are `method: 'plain'` and `port: 389`, OR
`method: 'ssl'` and `port: 636`.
-### Login with valid credentials rejected
+### Troubleshooting
+
+If a user account is blocked or unblocked due to the LDAP configuration, a
+message will be logged to `application.log`.
-If there is an unexpected error while authenticating the user with the LDAP
-backend, the login is rejected and details about the error are logged to
+If there is an unexpected error during an LDAP lookup (configuration error,
+timeout), the login is rejected and a message will be logged to
`production.log`.
diff --git a/doc/administration/auth/okta.md b/doc/administration/auth/okta.md
new file mode 100644
index 00000000000..cb42b7743c5
--- /dev/null
+++ b/doc/administration/auth/okta.md
@@ -0,0 +1,160 @@
+# Okta SSO provider
+
+Okta is a [Single Sign-on provider][okta-sso] that can be used to authenticate
+with GitLab.
+
+The following documentation enables Okta as a SAML provider.
+
+## Configure the Okta application
+
+1. On Okta go to the admin section and choose to **Add an App**.
+1. When the app screen comes up you see another button to **Create an App** and
+ choose SAML 2.0 on the next screen.
+1. Now, very important, add a logo
+ (you can choose it from https://about.gitlab.com/press/). You'll have to
+ crop and resize it.
+1. Next, you'll need the to fill in the SAML general config. Here's an example
+ image.
+
+ ![Okta admin panel view](img/okta_admin_panel.png)
+
+1. The last part of the configuration is the feedback section where you can
+ just say you're a customer and creating an app for internal use.
+1. When you have your app you'll have a few tabs on the top of the app's
+ profile. Click on the SAML 2.0 config instructions button which should
+ look like the following:
+
+ ![Okta SAML settings](img/okta_saml_settings.png)
+
+1. On the screen that comes up take note of the
+ **Identity Provider Single Sign-On URL** which you'll use for the
+ `idp_sso_target_url` on your GitLab config file.
+
+1. **Before you leave Okta make sure you add your user and groups if any.**
+
+---
+
+Now that the Okta app is configured, it's time to enable it in GitLab.
+
+## Configure GitLab
+
+1. On your GitLab server, open the configuration file:
+
+ **For Omnibus GitLab installations**
+
+ ```sh
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
+
+ **For installations from source**
+
+ ```sh
+ cd /home/git/gitlab
+ sudo -u git -H editor config/gitlab.yml
+ ```
+
+1. See [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration)
+ for initial settings.
+
+1. To allow your users to use Okta to sign up without having to manually create
+ an account first, don't forget to add the following values to your
+ configuration:
+
+ **For Omnibus GitLab installations**
+
+ ```ruby
+ gitlab_rails['omniauth_allow_single_sign_on'] = ['saml']
+ gitlab_rails['omniauth_block_auto_created_users'] = false
+ ```
+
+ **For installations from source**
+
+ ```yaml
+ allow_single_sign_on: ["saml"]
+ block_auto_created_users: false
+ ```
+
+1. You can also automatically link Okta users with existing GitLab users if
+ their email addresses match by adding the following setting:
+
+ **For Omnibus GitLab installations**
+
+ ```ruby
+ gitlab_rails['omniauth_auto_link_saml_user'] = true
+ ```
+
+ **For installations from source**
+
+ ```yaml
+ auto_link_saml_user: true
+ ```
+
+1. Add the provider configuration.
+
+ >**Notes:**
+ >- Change the value for `assertion_consumer_service_url` to match the HTTPS endpoint
+ of GitLab (append `users/auth/saml/callback` to the HTTPS URL of your GitLab
+ installation to generate the correct value).
+ >- To get the `idp_cert_fingerprint` fingerprint, first download the
+ certificate from the Okta app you registered and then run:
+ `openssl x509 -in okta.cert -noout -fingerprint`. Substitute `okta.cert`
+ with the location of your certificate.
+ >- Change the value of `idp_sso_target_url`, with the value of the
+ **Identity Provider Single Sign-On URL** from the step when you
+ configured the Okta app.
+ >- Change the value of `issuer` to a unique name, which will identify the application
+ to the IdP.
+ >- Leave `name_identifier_format` as-is.
+
+ **For Omnibus GitLab installations**
+
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ name: 'saml',
+ args: {
+ assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
+ idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
+ idp_sso_target_url: 'https://gitlab.oktapreview.com/app/gitlabdev773716_gitlabsaml_1/exk8odl81tBrjpD4B0h7/sso/saml',
+ issuer: 'https://gitlab.example.com',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
+ },
+ label: 'Okta' # optional label for SAML login button, defaults to "Saml"
+ }
+ ]
+ ```
+
+ **For installations from source**
+
+ ```yaml
+ - {
+ name: 'saml',
+ args: {
+ assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
+ idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
+ idp_sso_target_url: 'https://gitlab.oktapreview.com/app/gitlabdev773716_gitlabsaml_1/exk8odl81tBrjpD4B0h7/sso/saml',
+ issuer: 'https://gitlab.example.com',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
+ },
+ label: 'Okta' # optional label for SAML login button, defaults to "Saml"
+ }
+ ```
+
+
+1. [Reconfigure][reconf] or [restart] GitLab for Omnibus and installations
+ from source respectively for the changes to take effect.
+
+You might want to try this out on a incognito browser window.
+
+## Configuring groups
+
+>**Note:**
+Make sure the groups exist and are assigned to the Okta app.
+
+You can take a look of the [SAML documentation][saml] on external groups since
+it works the same.
+
+[okta-sso]: https://www.okta.com/products/single-sign-on/
+[saml]: ../../integration/saml.md#external-groups
+[reconf]: ../restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart]: ../restart_gitlab.md#installations-from-source
diff --git a/doc/administration/build_artifacts.md b/doc/administration/build_artifacts.md
index 64353f7282b..623a5321f32 100644
--- a/doc/administration/build_artifacts.md
+++ b/doc/administration/build_artifacts.md
@@ -1,90 +1 @@
-# Build artifacts administration
-
->**Notes:**
->- Introduced in GitLab 8.2 and GitLab Runner 0.7.0.
->- Starting from GitLab 8.4 and GitLab Runner 1.0, the artifacts archive format
- changed to `ZIP`.
->- This is the administration documentation. For the user guide see
- [user/project/builds/artifacts.md](../user/project/builds/artifacts.md).
-
-Artifacts is a list of files and directories which are attached to a build
-after it completes successfully. This feature is enabled by default in all
-GitLab installations. Keep reading if you want to know how to disable it.
-
-## Disabling build artifacts
-
-To disable artifacts site-wide, follow the steps below.
-
----
-
-**In Omnibus installations:**
-
-1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
-
- ```ruby
- gitlab_rails['artifacts_enabled'] = false
- ```
-
-1. Save the file and [reconfigure GitLab][] for the changes to take effect.
-
----
-
-**In installations from source:**
-
-1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines:
-
- ```yaml
- artifacts:
- enabled: false
- ```
-
-1. Save the file and [restart GitLab][] for the changes to take effect.
-
-## Storing build artifacts
-
-After a successful build, GitLab Runner uploads an archive containing the build
-artifacts to GitLab.
-
-To change the location where the artifacts are stored, follow the steps below.
-
----
-
-**In Omnibus installations:**
-
-_The artifacts are stored by default in
-`/var/opt/gitlab/gitlab-rails/shared/artifacts`._
-
-1. To change the storage path for example to `/mnt/storage/artifacts`, edit
- `/etc/gitlab/gitlab.rb` and add the following line:
-
- ```ruby
- gitlab_rails['artifacts_path'] = "/mnt/storage/artifacts"
- ```
-
-1. Save the file and [reconfigure GitLab][] for the changes to take effect.
-
----
-
-**In installations from source:**
-
-_The artifacts are stored by default in
-`/home/git/gitlab/shared/artifacts`._
-
-1. To change the storage path for example to `/mnt/storage/artifacts`, edit
- `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines:
-
- ```yaml
- artifacts:
- enabled: true
- path: /mnt/storage/artifacts
- ```
-
-1. Save the file and [restart GitLab][] for the changes to take effect.
-
-## Set the maximum file size of the artifacts
-
-Provided the artifacts are enabled, you can change the maximum file size of the
-artifacts through the [Admin area settings](../user/admin_area/settings/continuous_integration#maximum-artifacts-size).
-
-[reconfigure gitlab]: restart_gitlab.md "How to restart GitLab"
-[restart gitlab]: restart_gitlab.md "How to restart GitLab"
+This document was moved to [job_artifacts](job_artifacts.md).
diff --git a/doc/administration/container_registry.md b/doc/administration/container_registry.md
index d7cfb464f74..afafb6bf1f5 100644
--- a/doc/administration/container_registry.md
+++ b/doc/administration/container_registry.md
@@ -1,10 +1,7 @@
# GitLab Container Registry administration
-> [Introduced][ce-4040] in GitLab 8.8.
-
----
-
> **Notes:**
+- [Introduced][ce-4040] in GitLab 8.8.
- Container Registry manifest `v1` support was added in GitLab 8.9 to support
Docker versions earlier than 1.10.
- This document is about the admin guide. To learn how to use GitLab Container
@@ -379,6 +376,10 @@ Read more about the individual driver's config options in the
filesystem. Remember to enable backups with your object storage provider if
desired.
+> **Important** Enabling storage driver other than `filesystem` would mean
+that your Docker client needs to be able to access the storage backend directly.
+So you must use an address that resolves and is accessible outside GitLab server.
+
---
**Omnibus GitLab installations**
@@ -462,18 +463,127 @@ If Registry is enabled in your GitLab instance, but you don't need it for your
project, you can disable it from your project's settings. Read the user guide
on how to achieve that.
+## Disable Container Registry but use GitLab as an auth endpoint
+
+You can disable the embedded Container Registry to use an external one, but
+still use GitLab as an auth endpoint.
+
+**Omnibus GitLab**
+1. Open `/etc/gitlab/gitlab.rb` and set necessary configurations:
+
+ ```ruby
+ registry['enable'] = false
+ gitlab_rails['registry_enabled'] = true
+ gitlab_rails['registry_host'] = "registry.gitlab.example.com"
+ gitlab_rails['registry_port'] = "5005"
+ gitlab_rails['registry_api_url'] = "http://localhost:5000"
+ gitlab_rails['registry_key_path'] = "/var/opt/gitlab/gitlab-rails/certificate.key"
+ gitlab_rails['registry_path'] = "/var/opt/gitlab/gitlab-rails/shared/registry"
+ gitlab_rails['registry_issuer'] = "omnibus-gitlab-issuer"
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. Open `/home/git/gitlab/config/gitlab.yml`, and edit the configuration settings under `registry`:
+
+ ```
+ ## Container Registry
+
+ registry:
+ enabled: true
+ host: "registry.gitlab.example.com"
+ port: "5005"
+ api_url: "http://localhost:5000"
+ path: /var/opt/gitlab/gitlab-rails/shared/registry
+ key: /var/opt/gitlab/gitlab-rails/certificate.key
+ issuer: omnibus-gitlab-issuer
+ ```
+
+1. Save the file and [restart GitLab][] for the changes to take effect.
+
## Storage limitations
Currently, there is no storage limitation, which means a user can upload an
infinite amount of Docker images with arbitrary sizes. This setting will be
configurable in future releases.
-## Changelog
+## Configure Container Registry notifications
+
+You can configure the Container Registry to send webhook notifications in
+response to events happening within the registry.
+
+Read more about the Container Registry notifications config options in the
+[Docker Registry notifications documentation][notifications-config].
+
+>**Note:**
+Multiple endpoints can be configured for the Container Registry.
+
+
+**Omnibus GitLab installations**
+
+To configure a notification endpoint in Omnibus:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ registry['notifications'] = [
+ {
+ 'name' => 'test_endpoint',
+ 'url' => 'https://gitlab.example.com/notify',
+ 'timeout' => '500ms',
+ 'threshold' => 5,
+ 'backoff' => '1s',
+ 'headers' => {
+ "Authorization" => ["AUTHORIZATION_EXAMPLE_TOKEN"]
+ }
+ }
+ ]
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+---
+
+**Installations from source**
+
+Configuring the notification endpoint is done in your registry config YML file created
+when you [deployed your docker registry][registry-deploy].
+
+Example:
+
+```
+notifications:
+ endpoints:
+ - name: alistener
+ disabled: false
+ url: https://my.listener.com/event
+ headers: <http.Header>
+ timeout: 500
+ threshold: 5
+ backoff: 1000
+```
+
+## Using self-signed certificates with Container Registry
+
+If you're using a self-signed certificate with your Container Registry, you
+might encounter issues during the CI jobs like the following:
+
+```
+Error response from daemon: Get registry.example.com/v1/users/: x509: certificate signed by unknown authority
+```
-**GitLab 8.8 ([source docs][8-8-docs])**
+The Docker daemon running the command expects a cert signed by a recognized CA,
+thus the error above.
-- GitLab Container Registry feature was introduced.
+While GitLab doesn't support using self-signed certificates with Container
+Registry out of the box, it is possible to make it work if you follow
+[Docker's documentation][docker-insecure]. You may find some additional
+information in [issue 18239][ce-18239].
+[ce-18239]: https://gitlab.com/gitlab-org/gitlab-ce/issues/18239
+[docker-insecure]: https://docs.docker.com/registry/insecure/#using-self-signed-certificates
[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure
[restart gitlab]: restart_gitlab.md#installations-from-source
[wildcard certificate]: https://en.wikipedia.org/wiki/Wildcard_certificate
@@ -488,3 +598,5 @@ configurable in future releases.
[registry-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/nginx/registry-ssl
[existing-domain]: #configure-container-registry-under-an-existing-gitlab-domain
[new-domain]: #configure-container-registry-under-its-own-domain
+[notifications-config]: https://docs.docker.com/registry/notifications/
+[registry-notifications-config]: https://docs.docker.com/registry/configuration/#notifications
diff --git a/doc/administration/custom_hooks.md b/doc/administration/custom_hooks.md
index 0387d730489..4d35b20d0c3 100644
--- a/doc/administration/custom_hooks.md
+++ b/doc/administration/custom_hooks.md
@@ -3,7 +3,7 @@
>
**Note:** Custom Git hooks must be configured on the filesystem of the GitLab
server. Only GitLab server administrators will be able to complete these tasks.
-Please explore [webhooks](../web_hooks/web_hooks.md) as an option if you do not
+Please explore [webhooks] as an option if you do not
have filesystem access. For a user configurable Git hook interface, please see
[GitLab Enterprise Edition Git Hooks](http://docs.gitlab.com/ee/git_hooks/git_hooks.html).
@@ -42,6 +42,33 @@ Follow the steps below to set up a custom hook:
That's it! Assuming the hook code is properly implemented the hook will fire
as appropriate.
+## Chained hooks support
+
+> [Introduced][93] in GitLab Shell 4.1.0 and GitLab 8.15.
+
+Hooks can be also placed in `hooks/<hook_name>.d` (global) or
+`custom_hooks/<hook_name>.d` (per project) directories supporting chained
+execution of the hooks.
+
+To look in a different directory for the global custom hooks (those in
+`hooks/<hook_name.d>`), set `custom_hooks_dir` in gitlab-shell config. For
+Omnibus installations, this can be set in `gitlab.rb`; and in source
+installations, this can be set in `gitlab-shell/config.yml`.
+
+The hooks are searched and executed in this order:
+
+1. `<project>.git/hooks/` - symlink to `gitlab-shell/hooks` global dir
+1. `<project>.git/hooks/<hook_name>` - executed by `git` itself, this is `gitlab-shell/hooks/<hook_name>`
+1. `<project>.git/custom_hooks/<hook_name>` - per project hook (this is already existing behavior)
+1. `<project>.git/custom_hooks/<hook_name>.d/*` - per project hooks
+1. `<project>.git/hooks/<hook_name>.d/*` OR `<custom_hooks_dir>/<hook_name.d>/*` - global hooks: all executable files (minus editor backup files)
+
+Files in `.d` directories need to be executable and not match the backup file
+pattern (`*~`).
+
+The hooks of the same type are executed in order and execution stops on the
+first script exiting with a non-zero value.
+
## Custom error messages
> [Introduced][5073] in GitLab 8.10.
@@ -53,4 +80,6 @@ STDERR takes precedence over STDOUT.
![Custom message from custom Git hook](img/custom_hooks_error_msg.png)
[hooks]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#Server-Side-Hooks
+[webhooks]: ../user/project/integrations/webhooks.md
[5073]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5073
+[93]: https://gitlab.com/gitlab-org/gitlab-shell/merge_requests/93
diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md
index b4a953d1ccc..9bcd13a52f7 100644
--- a/doc/administration/environment_variables.md
+++ b/doc/administration/environment_variables.md
@@ -13,17 +13,18 @@ override certain values.
Variable | Type | Description
-------- | ---- | -----------
-`GITLAB_ROOT_PASSWORD` | string | Sets the password for the `root` user on installation
-`GITLAB_HOST` | string | The full URL of the GitLab server (including `http://` or `https://`)
-`RAILS_ENV` | string | The Rails environment; can be one of `production`, `development`, `staging` or `test`
-`DATABASE_URL` | string | The database URL; is of the form: `postgresql://localhost/blog_development`
-`GITLAB_EMAIL_FROM` | string | The e-mail address used in the "From" field in e-mails sent by GitLab
-`GITLAB_EMAIL_DISPLAY_NAME` | string | The name used in the "From" field in e-mails sent by GitLab
-`GITLAB_EMAIL_REPLY_TO` | string | The e-mail address used in the "Reply-To" field in e-mails sent by GitLab
-`GITLAB_EMAIL_REPLY_TO` | string | The e-mail address used in the "Reply-To" field in e-mails sent by GitLab
-`GITLAB_EMAIL_SUBJECT_SUFFIX` | string | The e-mail subject suffix used in e-mails sent by GitLab
-`GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer
-`GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer
+`GITLAB_CDN_HOST` | string | Sets the hostname for a CDN to serve static assets (e.g. `mycdnsubdomain.fictional-cdn.com`)
+`GITLAB_ROOT_PASSWORD` | string | Sets the password for the `root` user on installation
+`GITLAB_HOST` | string | The full URL of the GitLab server (including `http://` or `https://`)
+`RAILS_ENV` | string | The Rails environment; can be one of `production`, `development`, `staging` or `test`
+`DATABASE_URL` | string | The database URL; is of the form: `postgresql://localhost/blog_development`
+`GITLAB_EMAIL_FROM` | string | The e-mail address used in the "From" field in e-mails sent by GitLab
+`GITLAB_EMAIL_DISPLAY_NAME` | string | The name used in the "From" field in e-mails sent by GitLab
+`GITLAB_EMAIL_REPLY_TO` | string | The e-mail address used in the "Reply-To" field in e-mails sent by GitLab
+`GITLAB_EMAIL_SUBJECT_SUFFIX` | string | The e-mail subject suffix used in e-mails sent by GitLab
+`GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer
+`GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer
+`GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN` | string | Sets the initial registration token used for GitLab Runners
## Complete database variables
@@ -58,6 +59,9 @@ to the naming scheme `GITLAB_#{name in 1_settings.rb in upper case}`.
## Omnibus configuration
+To set environment variables, follow [these
+instructions](https://docs.gitlab.com/omnibus/settings/environment-variables.html).
+
It's possible to preconfigure the GitLab docker image by adding the environment
variable `GITLAB_OMNIBUS_CONFIG` to the `docker run` command.
For more information see the ['preconfigure-docker-container' section in the Omnibus documentation](http://docs.gitlab.com/omnibus/docker/#preconfigure-docker-container).
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
new file mode 100644
index 00000000000..332457cb384
--- /dev/null
+++ b/doc/administration/gitaly/index.md
@@ -0,0 +1,223 @@
+# Gitaly
+
+[Gitaly](https://gitlab.com/gitlab-org/gitaly) (introduced in GitLab
+9.0) is a service that provides high-level RPC access to Git
+repositories. As of GitLab 9.3 it is still an optional component with
+limited scope.
+
+GitLab components that access Git repositories (gitlab-rails,
+gitlab-shell, gitlab-workhorse) act as clients to Gitaly. End users do
+not have direct access to Gitaly.
+
+## Configuring Gitaly
+
+The Gitaly service itself is configured via a TOML configuration file.
+This file is documented [in the gitaly
+repository](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/configuration/README.md).
+
+To change a Gitaly setting in Omnibus you can use
+`gitaly['my_setting']` in `/etc/gitlab/gitlab.rb`. Changes will be applied
+when you run `gitlab-ctl reconfigure`.
+
+```ruby
+gitaly['prometheus_listen_addr'] = 'localhost:9236'
+```
+
+To change a Gitaly setting in installations from source you can edit
+`/home/git/gitaly/config.toml`.
+
+```toml
+prometheus_listen_addr = "localhost:9236"
+```
+
+Changes to `/home/git/gitaly/config.toml` are applied when you run `service
+gitlab restart`.
+
+## Running Gitaly on its own server
+
+> This is an optional way to deploy Gitaly which can benefit GitLab
+installations that are larger than a single machine. Most
+installations will be better served with the default configuration
+used by Omnibus and the GitLab source installation guide.
+
+Starting with GitLab 9.4 it is possible to run Gitaly on a different
+server from the rest of the application. This can improve performance
+when running GitLab with its repositories stored on an NFS server.
+
+At the moment (GitLab 9.4) Gitaly is not yet a replacement for NFS
+because some parts of GitLab still bypass Gitaly when accessing Git
+repositories. If you choose to deploy Gitaly on your NFS server you
+must still also mount your Git shares on your GitLab application
+servers.
+
+Gitaly network traffic is unencrypted so you should use a firewall to
+restrict access to your Gitaly server.
+
+Below we describe how to configure a Gitaly server at address
+`gitaly.internal:9999` with secret token `abc123secret`. We assume
+your GitLab installation has two repository storages, `default` and
+`storage1`.
+
+### Client side token configuration
+
+Start by configuring a token on the client side.
+
+Omnibus installations:
+
+```ruby
+# /etc/gitlab/gitlab.rb
+gitlab_rails['gitaly_token'] = 'abc123secret'
+```
+
+Source installations:
+
+```yaml
+# /home/git/gitlab/config/gitlab.yml
+gitlab:
+ gitaly:
+ token: 'abc123secret'
+```
+
+You need to reconfigure (Omnibus) or restart (source) for these
+changes to be picked up.
+
+### Gitaly server configuration
+
+Next, on the Gitaly server, we need to configure storage paths, enable
+the network listener and configure the token.
+
+Note: if you want to reduce the risk of downtime when you enable
+authentication you can temporarily disable enforcement, see [the
+documentation on configuring Gitaly
+authentication](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/configuration/README.md#authentication)
+.
+
+In most or all cases the storage paths below end in `/repositories`. Check the
+directory layout on your Gitaly server to be sure.
+
+Omnibus installations:
+
+```ruby
+# /etc/gitlab/gitlab.rb
+gitaly['listen_addr'] = '0.0.0.0:9999'
+gitaly['auth_token'] = 'abc123secret'
+gitaly['storage'] = [
+ { 'name' => 'default', 'path' => '/path/to/default/repositories' },
+ { 'name' => 'storage1', 'path' => '/path/to/storage1/repositories' },
+]
+```
+
+Source installations:
+
+```toml
+# /home/git/gitaly/config.toml
+listen_addr = '0.0.0.0:9999'
+
+[auth]
+token = 'abc123secret'
+
+[[storage]
+name = 'default'
+path = '/path/to/default/repositories'
+
+[[storage]]
+name = 'storage1'
+path = '/path/to/storage1/repositories'
+```
+
+Again, reconfigure (Omnibus) or restart (source).
+
+### Converting clients to use the Gitaly server
+
+Now as the final step update the client machines to switch from using
+their local Gitaly service to the new Gitaly server you just
+configured. This is a risky step because if there is any sort of
+network, firewall, or name resolution problem preventing your GitLab
+server from reaching the Gitaly server then all Gitaly requests will
+fail.
+
+We assume that your Gitaly server can be reached at
+`gitaly.internal:9999` from your GitLab server, and that your GitLab
+NFS shares are mounted at `/mnt/gitlab/default` and
+`/mnt/gitlab/storage1` respectively.
+
+Omnibus installations:
+
+```ruby
+# /etc/gitlab/gitlab.rb
+git_data_dirs({
+ { 'default' => { 'path' => '/mnt/gitlab/default', 'gitaly_address' => 'tcp://gitlab.internal:9999' } },
+ { 'storage1' => { 'path' => '/mnt/gitlab/storage1', 'gitaly_address' => 'tcp://gitlab.internal:9999' } },
+})
+```
+
+Source installations:
+
+```yaml
+# /home/git/gitlab/config/gitlab.yml
+gitlab:
+ repositories:
+ storages:
+ default:
+ path: /mnt/gitlab/default/repositories
+ gitaly_address: tcp://gitlab.internal:9999
+ storage1:
+ path: /mnt/gitlab/storage1/repositories
+ gitaly_address: tcp://gitlab.internal:9999
+```
+
+Now reconfigure (Omnibus) or restart (source). When you tail the
+Gitaly logs on your Gitaly server (`sudo gitlab-ctl tail gitaly` or
+`tail -f /home/git/gitlab/log/gitaly.log`) you should see requests
+coming in. One sure way to trigger a Gitaly request is to clone a
+repository from your GitLab server over HTTP.
+
+## Configuring GitLab to not use Gitaly
+
+Gitaly is still an optional component in GitLab 9.3. This means you
+can choose to not use it.
+
+In Omnibus you can make the following change in
+`/etc/gitlab/gitlab.rb` and reconfigure. This will both disable the
+Gitaly service and configure the rest of GitLab not to use it.
+
+```ruby
+gitaly['enable'] = false
+```
+
+In source installations, edit `/home/git/gitlab/config/gitlab.yml` and
+make sure `enabled` in the `gitaly` section is set to 'false'. This
+does not disable the Gitaly service in your init script; it only
+prevents it from being used.
+
+Apply the change with `service gitlab restart`.
+
+```yaml
+ gitaly:
+ enabled: false
+```
+
+## Disabling or enabling the Gitaly service
+
+Be careful: if you disable Gitaly without instructing the rest of your
+GitLab installation not to use Gitaly, you may end up with errors
+because GitLab tries to access a service that is not running.
+
+To disable the Gitaly service in your Omnibus installation, add the
+following line to `/etc/gitlab/gitlab.rb`:
+
+```ruby
+gitaly['enable'] = false
+```
+
+When you run `gitlab-ctl reconfigure` the Gitaly service will be
+disabled.
+
+To disable the Gitaly service in an installation from source, add the
+following to `/etc/default/gitlab`:
+
+```shell
+gitaly_enabled=false
+```
+
+When you run `service gitlab restart` Gitaly will be disabled. \ No newline at end of file
diff --git a/doc/administration/high_availability/README.md b/doc/administration/high_availability/README.md
index d74a786ac24..4d3be0ab8f6 100644
--- a/doc/administration/high_availability/README.md
+++ b/doc/administration/high_availability/README.md
@@ -5,21 +5,26 @@ The solution you choose will be based on the level of scalability and
availability you require. The easiest solutions are scalable, but not necessarily
highly available.
-## Architecture
-
-### Active/Passive
-
-For pure high-availability/failover with no scaling you can use an
-active/passive configuration. This utilizes DRBD (Distributed Replicated
-Block Device) to keep all data in sync. DRBD requires a low latency link to
-remain in sync. It is not advisable to attempt to run DRBD between data centers
-or in different cloud availability zones.
+GitLab provides a service that is usually essential to most organizations: it
+enables people to collaborate on code in a timely fashion. Any downtime should
+therefore be short and planned. Luckily, GitLab provides a solid setup even on
+a single server without special measures. Due to the distributed nature
+of Git, developers can still commit code locally even when GitLab is not
+available. However, some GitLab features such as the issue tracker and
+Continuous Integration are not available when GitLab is down.
+
+**Keep in mind that all Highly Available solutions come with a trade-off between
+cost/complexity and uptime**. The more uptime you want, the more complex the
+solution. And the more complex the solution, the more work is involved in
+setting up and maintaining it. High availability is not free and every HA
+solution should balance the costs against the benefits.
-Components/Servers Required:
+## Architecture
-- 2 servers/virtual machines (one active/one passive)
+There are two kinds of setups:
-![Active/Passive HA Diagram](../img/high_availability/active-passive-diagram.png)
+- active/active
+- active/passive
### Active/Active
@@ -28,12 +33,28 @@ user requests simultaneously. The database, Redis, and GitLab application are
all deployed on separate servers. The configuration is **only** highly-available
if the database, Redis and storage are also configured as such.
-![Active/Active HA Diagram](../img/high_availability/active-active-diagram.png)
-
-**Steps to configure active/active:**
+Follow the steps below to configure an active/active setup:
1. [Configure the database](database.md)
1. [Configure Redis](redis.md)
1. [Configure NFS](nfs.md)
1. [Configure the GitLab application servers](gitlab.md)
1. [Configure the load balancers](load_balancer.md)
+
+![Active/Active HA Diagram](../img/high_availability/active-active-diagram.png)
+
+### Active/Passive
+
+For pure high-availability/failover with no scaling you can use an
+active/passive configuration. This utilizes DRBD (Distributed Replicated
+Block Device) to keep all data in sync. DRBD requires a low latency link to
+remain in sync. It is not advisable to attempt to run DRBD between data centers
+or in different cloud availability zones.
+
+> **Note:** GitLab recommends against choosing this HA method because of the
+ complexity of managing DRBD and crafting automatic failover. This is
+ *compatible* with GitLab, but not officially *supported*.
+
+Components/Servers Required: 2 servers/virtual machines (one active/one passive)
+
+![Active/Passive HA Diagram](../img/high_availability/active-passive-diagram.png)
diff --git a/doc/administration/high_availability/database.md b/doc/administration/high_availability/database.md
index 538dada1bae..da9687aa849 100644
--- a/doc/administration/high_availability/database.md
+++ b/doc/administration/high_availability/database.md
@@ -13,10 +13,12 @@ Database Service (RDS) that runs PostgreSQL.
If you use a cloud-managed service, or provide your own PostgreSQL:
+1. Setup PostgreSQL according to the
+ [database requirements document](../../install/requirements.md#database).
1. Set up a `gitlab` username with a password of your choice. The `gitlab` user
needs privileges to create the `gitlabhq_production` database.
1. Configure the GitLab application servers with the appropriate details.
- This step is covered in [Configuring GitLab for HA](gitlab.md)
+ This step is covered in [Configuring GitLab for HA](gitlab.md).
## Configure using Omnibus
@@ -25,7 +27,7 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
steps on the download page.
1. Create/edit `/etc/gitlab/gitlab.rb` and use the following configuration.
Be sure to change the `external_url` to match your eventual GitLab front-end
- URL.
+ URL. If there is a directive listed below that you do not see in the configuration, be sure to add it.
```ruby
external_url 'https://gitlab.example.com'
@@ -37,13 +39,18 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
unicorn['enable'] = false
sidekiq['enable'] = false
redis['enable'] = false
+ prometheus['enable'] = false
+ gitaly['enable'] = false
gitlab_workhorse['enable'] = false
mailroom['enable'] = false
# PostgreSQL configuration
- postgresql['sql_password'] = 'DB password'
+ gitlab_rails['db_password'] = 'DB password'
postgresql['md5_auth_cidr_addresses'] = ['0.0.0.0/0']
postgresql['listen_address'] = '0.0.0.0'
+
+ # Disable automatic database migrations
+ gitlab_rails['auto_migrate'] = false
```
1. Run `sudo gitlab-ctl reconfigure` to install and configure PostgreSQL.
@@ -80,7 +87,7 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
1. Similarly, set the password for the `gitlab` database user. Use the same
password that you specified in the `/etc/gitlab/gitlab.rb` file for
- `postgresql['sql_password']`.
+ `gitlab_rails['db_password']`.
```
\password gitlab
@@ -102,9 +109,8 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
1. Exit the database prompt by typing `\q` and Enter.
1. Exit the `gitlab-psql` user by running `exit` twice.
1. Run `sudo gitlab-ctl reconfigure` a final time.
-1. Run `touch /etc/gitlab/skip-auto-migrations` to prevent database migrations
- from running on upgrade. Only the primary GitLab application server should
- handle migrations.
+1. Configure the GitLab application servers with the appropriate details.
+ This step is covered in [Configuring GitLab for HA](gitlab.md).
---
diff --git a/doc/administration/high_availability/gitlab.md b/doc/administration/high_availability/gitlab.md
index 8a881ce8863..137fed35a73 100644
--- a/doc/administration/high_availability/gitlab.md
+++ b/doc/administration/high_availability/gitlab.md
@@ -101,9 +101,9 @@ need some additional configuration.
```ruby
gitlab_shell['secret_token'] = 'fbfb19c355066a9afb030992231c4a363357f77345edd0f2e772359e5be59b02538e1fa6cae8f93f7d23355341cea2b93600dab6d6c3edcdced558fc6d739860'
- gitlab_rails['secret_token'] = 'b719fe119132c7810908bba18315259ed12888d4f5ee5430c42a776d840a396799b0a5ef0a801348c8a357f07aa72bbd58e25a84b8f247a25c72f539c7a6c5fa'
- gitlab_ci['secret_key_base'] = '6e657410d57c71b4fc3ed0d694e7842b1895a8b401d812c17fe61caf95b48a6d703cb53c112bc01ebd197a85da81b18e29682040e99b4f26594772a4a2c98c6d'
- gitlab_ci['db_key_base'] = 'bf2e47b68d6cafaef1d767e628b619365becf27571e10f196f98dc85e7771042b9203199d39aff91fcb6837c8ed83f2a912b278da50999bb11a2fbc0fba52964'
+ gitlab_rails['otp_key_base'] = 'b719fe119132c7810908bba18315259ed12888d4f5ee5430c42a776d840a396799b0a5ef0a801348c8a357f07aa72bbd58e25a84b8f247a25c72f539c7a6c5fa'
+ gitlab_rails['secret_key_base'] = '6e657410d57c71b4fc3ed0d694e7842b1895a8b401d812c17fe61caf95b48a6d703cb53c112bc01ebd197a85da81b18e29682040e99b4f26594772a4a2c98c6d'
+ gitlab_rails['db_key_base'] = 'bf2e47b68d6cafaef1d767e628b619365becf27571e10f196f98dc85e7771042b9203199d39aff91fcb6837c8ed83f2a912b278da50999bb11a2fbc0fba52964'
```
1. Run `touch /etc/gitlab/skip-auto-migrations` to prevent database migrations
diff --git a/doc/administration/high_availability/load_balancer.md b/doc/administration/high_availability/load_balancer.md
index 136f570ac27..359de0efadb 100644
--- a/doc/administration/high_availability/load_balancer.md
+++ b/doc/administration/high_availability/load_balancer.md
@@ -10,29 +10,30 @@ you need to use with GitLab.
## Basic ports
-| LB Port | Backend Port | Protocol |
-| ------- | ------------ | -------- |
-| 80 | 80 | HTTP |
-| 443 | 443 | HTTPS [^1] |
-| 22 | 22 | TCP |
+| LB Port | Backend Port | Protocol |
+| ------- | ------------ | --------------- |
+| 80 | 80 | HTTP [^1] |
+| 443 | 443 | TCP or HTTPS [^1] [^2] |
+| 22 | 22 | TCP |
## GitLab Pages Ports
-If you're using GitLab Pages you will need some additional port configurations.
-GitLab Pages requires a separate VIP. Configure DNS to point the
-`pages_external_url` from `/etc/gitlab/gitlab.rb` at the new VIP. See the
+If you're using GitLab Pages with custom domain support you will need some
+additional port configurations.
+GitLab Pages requires a separate virtual IP address. Configure DNS to point the
+`pages_external_url` from `/etc/gitlab/gitlab.rb` at the new virtual IP address. See the
[GitLab Pages documentation][gitlab-pages] for more information.
| LB Port | Backend Port | Protocol |
| ------- | ------------ | -------- |
-| 80 | Varies [^2] | HTTP |
-| 443 | Varies [^2] | TCP [^3] |
+| 80 | Varies [^3] | HTTP |
+| 443 | Varies [^3] | TCP [^4] |
## Alternate SSH Port
Some organizations have policies against opening SSH port 22. In this case,
it may be helpful to configure an alternate SSH hostname that allows users
-to use SSH on port 443. An alternate SSH hostname will require a new VIP
+to use SSH on port 443. An alternate SSH hostname will require a new virtual IP address
compared to the other GitLab HTTP configuration above.
Configure DNS for an alternate SSH hostname such as altssh.gitlab.example.com.
@@ -50,14 +51,20 @@ Read more on high-availability configuration:
1. [Configure NFS](nfs.md)
1. [Configure the GitLab application servers](gitlab.md)
-[^1]: When using HTTPS protocol for port 443, you will need to add an SSL
+[^1]: [Web terminal](../../ci/environments.md#web-terminals) support requires
+ your load balancer to correctly handle WebSocket connections. When using
+ HTTP or HTTPS proxying, this means your load balancer must be configured
+ to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the
+ [web terminal](../integration/terminal.md) integration guide for
+ more details.
+[^2]: When using HTTPS protocol for port 443, you will need to add an SSL
certificate to the load balancers. If you wish to terminate SSL at the
GitLab application server instead, use TCP protocol.
-[^2]: The backend port for GitLab Pages depends on the
+[^3]: The backend port for GitLab Pages depends on the
`gitlab_pages['external_http']` and `gitlab_pages['external_https']`
setting. See [GitLab Pages documentation][gitlab-pages] for more details.
-[^3]: Port 443 for GitLab Pages should always use the TCP protocol. Users can
+[^4]: Port 443 for GitLab Pages should always use the TCP protocol. Users can
configure custom domains with custom SSL, which would not be possible
if SSL was terminated at the load balancer.
-[gitlab-pages]: http://docs.gitlab.com/ee/pages/administration.html
+[gitlab-pages]: ../pages/index.md
diff --git a/doc/administration/high_availability/nfs.md b/doc/administration/high_availability/nfs.md
index 537f4f3501d..bd6b7327aed 100644
--- a/doc/administration/high_availability/nfs.md
+++ b/doc/administration/high_availability/nfs.md
@@ -1,34 +1,58 @@
# NFS
-## Required NFS Server features
+You can view information and options set for each of the mounted NFS file
+systems by running `sudo nfsstat -m`.
+
+## NFS Server features
+
+### Required features
**File locking**: GitLab **requires** advisory file locking, which is only
supported natively in NFS version 4. NFSv3 also supports locking as long as
Linux Kernel 2.6.5+ is used. We recommend using version 4 and do not
specifically test NFSv3.
-**no_root_squash**: NFS normally changes the `root` user to `nobody`. This is
-a good security measure when NFS shares will be accessed by many different
-users. However, in this case only GitLab will use the NFS share so it
-is safe. GitLab requires the `no_root_squash` setting because we need to
-manage file permissions automatically. Without the setting you will receive
-errors when the Omnibus package tries to alter permissions. Note that GitLab
-and other bundled components do **not** run as `root` but as non-privileged
-users. The requirement for `no_root_squash` is to allow the Omnibus package to
-set ownership and permissions on files, as needed.
-
### Recommended options
When you define your NFS exports, we recommend you also add the following
options:
+- `no_root_squash` - NFS normally changes the `root` user to `nobody`. This is
+ a good security measure when NFS shares will be accessed by many different
+ users. However, in this case only GitLab will use the NFS share so it
+ is safe. GitLab recommends the `no_root_squash` setting because we need to
+ manage file permissions automatically. Without the setting you may receive
+ errors when the Omnibus package tries to alter permissions. Note that GitLab
+ and other bundled components do **not** run as `root` but as non-privileged
+ users. The recommendation for `no_root_squash` is to allow the Omnibus package
+ to set ownership and permissions on files, as needed.
- `sync` - Force synchronous behavior. Default is asynchronous and under certain
circumstances it could lead to data loss if a failure occurs before data has
synced.
-## Client mount options
+## AWS Elastic File System
+
+GitLab does not recommend using AWS Elastic File System (EFS).
+
+Customers and users have reported that AWS EFS does not perform well for GitLab's
+use-case. There are several issues that can cause problems. For these reasons
+GitLab does not recommend using EFS with GitLab.
+
+- EFS bases allowed IOPS on volume size. The larger the volume, the more IOPS
+ are allocated. For smaller volumes, users may experience decent performance
+ for a period of time due to 'Burst Credits'. Over a period of weeks to months
+ credits may run out and performance will bottom out.
+- For larger volumes, allocated IOPS may not be the problem. Workloads where
+ many small files are written in a serialized manner are not well-suited for EFS.
+ EBS with an NFS server on top will perform much better.
+
+For more details on another person's experience with EFS, see
+[Amazon's Elastic File System: Burst Credits](https://www.rawkode.io/2017/04/amazons-elastic-file-system-burst-credits/)
+
+## NFS Client mount options
-Below is an example of an NFS mount point we use on GitLab.com:
+Below is an example of an NFS mount point defined in `/etc/fstab` we use on
+GitLab.com:
```
10.1.1.1:/var/opt/gitlab/git-data /var/opt/gitlab/git-data nfs4 defaults,soft,rsize=1048576,wsize=1048576,noatime,nobootwait,lookupcache=positive 0 2
@@ -47,13 +71,13 @@ When using default Omnibus configuration you will need to share 5 data locations
between all GitLab cluster nodes. No other locations should be shared. The
following are the 5 locations you need to mount:
-| Location | Description |
-| -------- | ----------- |
-| `/var/opt/gitlab/git-data` | Git repository data. This will account for a large portion of your data
-| `/var/opt/gitlab/.ssh` | SSH `authorized_keys` file and keys used to import repositories from some other Git services
-| `/var/opt/gitlab/gitlab-rails/uploads` | User uploaded attachments
-| `/var/opt/gitlab/gitlab-rails/shared` | Build artifacts, GitLab Pages, LFS objects, temp files, etc. If you're using LFS this may also account for a large portion of your data
-| `/var/opt/gitlab/gitlab-ci/builds` | GitLab CI build traces
+| Location | Description | Default configuration |
+| -------- | ----------- | --------------------- |
+| `/var/opt/gitlab/git-data` | Git repository data. This will account for a large portion of your data | `git_data_dirs({"default" => "/var/opt/gitlab/git-data"})`
+| `/var/opt/gitlab/.ssh` | SSH `authorized_keys` file and keys used to import repositories from some other Git services | `user['home'] = '/var/opt/gitlab/'`
+| `/var/opt/gitlab/gitlab-rails/uploads` | User uploaded attachments | `gitlab_rails['uploads_directory'] = '/var/opt/gitlab/gitlab-rails/uploads'`
+| `/var/opt/gitlab/gitlab-rails/shared` | Build artifacts, GitLab Pages, LFS objects, temp files, etc. If you're using LFS this may also account for a large portion of your data | `gitlab_rails['shared_path'] = '/var/opt/gitlab/gitlab-rails/shared'`
+| `/var/opt/gitlab/gitlab-ci/builds` | GitLab CI build traces | `gitlab_ci['builds_directory'] = '/var/opt/gitlab/gitlab-ci/builds'`
Other GitLab directories should not be shared between nodes. They contain
node-specific files and GitLab code that does not need to be shared. To ship
@@ -73,10 +97,10 @@ as subdirectories. Mount `/gitlab-data` then use the following Omnibus
configuration to move each data location to a subdirectory:
```ruby
+git_data_dirs({"default" => "/gitlab-data/git-data"})
user['home'] = '/gitlab-data/home'
-git_data_dir '/gitlab-data/git-data'
+gitlab_rails['uploads_directory'] = '/gitlab-data/uploads'
gitlab_rails['shared_path'] = '/gitlab-data/shared'
-gitlab_rails['uploads_directory'] = "/gitlab-data/uploads"
gitlab_ci['builds_directory'] = '/gitlab-data/builds'
```
diff --git a/doc/administration/high_availability/redis.md b/doc/administration/high_availability/redis.md
index bc424330656..0e92f7c5a34 100644
--- a/doc/administration/high_availability/redis.md
+++ b/doc/administration/high_availability/redis.md
@@ -1,265 +1,779 @@
# Configuring Redis for GitLab HA
-You can choose to install and manage Redis yourself, or you can use the one
-that comes bundled with GitLab Omnibus packages.
-
-> **Note:** Redis does not require authentication by default. See
+>
+Experimental Redis Sentinel support was [Introduced][ce-1877] in GitLab 8.11.
+Starting with 8.14, Redis Sentinel is no longer experimental.
+If you've used it with versions `< 8.14` before, please check the updated
+documentation here.
+
+High Availability with [Redis] is possible using a **Master** x **Slave**
+topology with a [Redis Sentinel][sentinel] service to watch and automatically
+start the failover procedure.
+
+You can choose to install and manage Redis and Sentinel yourself, use
+a hosted cloud solution or you can use the one that comes bundled with
+Omnibus GitLab packages.
+
+> **Notes:**
+- Redis requires authentication for High Availability. See
[Redis Security](http://redis.io/topics/security) documentation for more
information. We recommend using a combination of a Redis password and tight
firewall rules to secure your Redis service.
+- You are highly encouraged to read the [Redis Sentinel][sentinel] documentation
+ before configuring Redis HA with GitLab to fully understand the topology and
+ architecture.
+- This is the documentation for the Omnibus GitLab packages. For installations
+ from source, follow the [Redis HA source installation](redis_source.md) guide.
+- Redis Sentinel daemon is bundled with Omnibus GitLab Enterprise Edition only.
+ For configuring Sentinel with the Omnibus GitLab Community Edition and
+ installations from source, read the
+ [Available configuration setups](#available-configuration-setups) section
+ below.
+
+## Overview
+
+Before diving into the details of setting up Redis and Redis Sentinel for HA,
+make sure you read this Overview section to better understand how the components
+are tied together.
+
+You need at least `3` independent machines: physical, or VMs running into
+distinct physical machines. It is essential that all master and slaves Redis
+instances run in different machines. If you fail to provision the machines in
+that specific way, any issue with the shared environment can bring your entire
+setup down.
+
+It is OK to run a Sentinel alongside of a master or slave Redis instance.
+There should be no more than one Sentinel on the same machine though.
+
+You also need to take into consideration the underlying network topology,
+making sure you have redundant connectivity between Redis / Sentinel and
+GitLab instances, otherwise the networks will become a single point of
+failure.
+
+Make sure that you read this document once as a whole before configuring the
+components below.
+
+### High Availability with Sentinel
+
+>**Notes:**
+- Starting with GitLab `8.11`, you can configure a list of Redis Sentinel
+ servers that will monitor a group of Redis servers to provide failover support.
+- Starting with GitLab `8.14`, the Omnibus GitLab Enterprise Edition package
+ comes with Redis Sentinel daemon built-in.
+
+High Availability with Redis requires a few things:
+
+- Multiple Redis instances
+- Run Redis in a **Master** x **Slave** topology
+- Multiple Sentinel instances
+- Application support and visibility to all Sentinel and Redis instances
+
+Redis Sentinel can handle the most important tasks in an HA environment and that's
+to help keep servers online with minimal to no downtime. Redis Sentinel:
+
+- Monitors **Master** and **Slaves** instances to see if they are available
+- Promotes a **Slave** to **Master** when the **Master** fails
+- Demotes a **Master** to **Slave** when the failed **Master** comes back online
+ (to prevent data-partitioning)
+- Can be queried by the application to always connect to the current **Master**
+ server
+
+When a **Master** fails to respond, it's the application's responsibility
+(in our case GitLab) to handle timeout and reconnect (querying a **Sentinel**
+for a new **Master**).
-## Configure your own Redis server
+To get a better understanding on how to correctly setup Sentinel, please read
+the [Redis Sentinel documentation](http://redis.io/topics/sentinel) first, as
+failing to configure it correctly can lead to data loss or can bring your
+whole cluster down, invalidating the failover effort.
-If you're hosting GitLab on a cloud provider, you can optionally use a
-managed service for Redis. For example, AWS offers a managed ElastiCache service
-that runs Redis.
+### Recommended setup
-## Configure Redis using Omnibus
+For a minimal setup, you will install the Omnibus GitLab package in `3`
+**independent** machines, both with **Redis** and **Sentinel**:
-If you don't want to bother setting up your own Redis server, you can use the
-one bundled with Omnibus. In this case, you should disable all services except
-Redis.
+- Redis Master + Sentinel
+- Redis Slave + Sentinel
+- Redis Slave + Sentinel
-1. Download/install GitLab Omnibus using **steps 1 and 2** from
- [GitLab downloads](https://about.gitlab.com/downloads). Do not complete other
- steps on the download page.
-1. Create/edit `/etc/gitlab/gitlab.rb` and use the following configuration.
- Be sure to change the `external_url` to match your eventual GitLab front-end
- URL:
+If you are not sure or don't understand why and where the amount of nodes come
+from, read [Redis setup overview](#redis-setup-overview) and
+[Sentinel setup overview](#sentinel-setup-overview).
- ```ruby
- external_url 'https://gitlab.example.com'
-
- # Disable all services except Redis
- redis['enable'] = true
- bootstrap['enable'] = false
- nginx['enable'] = false
- unicorn['enable'] = false
- sidekiq['enable'] = false
- postgresql['enable'] = false
- gitlab_workhorse['enable'] = false
- mailroom['enable'] = false
-
- # Redis configuration
- redis['port'] = 6379
- redis['bind'] = '0.0.0.0'
+For a recommended setup that can resist more failures, you will install
+the Omnibus GitLab package in `5` **independent** machines, both with
+**Redis** and **Sentinel**:
- # If you wish to use Redis authentication (recommended)
- redis['password'] = 'Redis Password'
- ```
+- Redis Master + Sentinel
+- Redis Slave + Sentinel
+- Redis Slave + Sentinel
+- Redis Slave + Sentinel
+- Redis Slave + Sentinel
-1. Run `sudo gitlab-ctl reconfigure` to install and configure PostgreSQL.
+### Redis setup overview
- > **Note**: This `reconfigure` step will result in some errors.
- That's OK - don't be alarmed.
+You must have at least `3` Redis servers: `1` Master, `2` Slaves, and they
+need to each be on independent machines (see explanation above).
-1. Run `touch /etc/gitlab/skip-auto-migrations` to prevent database migrations
- from running on upgrade. Only the primary GitLab application server should
- handle migrations.
+You can have additional Redis nodes, that will help survive a situation
+where more nodes goes down. Whenever there is only `2` nodes online, a failover
+will not be initiated.
-## Experimental Redis Sentinel support
+As an example, if you have `6` Redis nodes, a maximum of `3` can be
+simultaneously down.
-> [Introduced][ce-1877] in GitLab 8.11.
+Please note that there are different requirements for Sentinel nodes.
+If you host them in the same Redis machines, you may need to take
+that restrictions into consideration when calculating the amount of
+nodes to be provisioned. See [Sentinel setup overview](#sentinel-setup-overview)
+documentation for more information.
-Since GitLab 8.11, you can configure a list of Redis Sentinel servers that
-will monitor a group of Redis servers to provide you with a standard failover
-support.
+All Redis nodes should be configured the same way and with similar server specs, as
+in a failover situation, any **Slave** can be promoted as the new **Master** by
+the Sentinel servers.
-There is currently one exception to the Sentinel support: `mail_room`, the
-component that processes incoming emails. It doesn't support Sentinel yet, but
-we hope to integrate a future release that does support it.
+The replication requires authentication, so you need to define a password to
+protect all Redis nodes and the Sentinels. They will all share the same
+password, and all instances must be able to talk to
+each other over the network.
-To get a better understanding on how to correctly setup Sentinel, please read
-the [Redis Sentinel documentation](http://redis.io/topics/sentinel) first, as
-failing to configure it correctly can lead to data loss.
+### Sentinel setup overview
-The configuration consists of three parts:
+Sentinels watch both other Sentinels and Redis nodes. Whenever a Sentinel
+detects that a Redis node is not responding, it will announce that to the
+other Sentinels. They have to reach the **quorum**, that is the minimum amount
+of Sentinels that agrees a node is down, in order to be able to start a failover.
-- Redis setup
-- Sentinel setup
-- GitLab setup
+Whenever the **quorum** is met, the **majority** of all known Sentinel nodes
+need to be available and reachable, so that they can elect the Sentinel **leader**
+who will take all the decisions to restore the service availability by:
-Read carefully how to configure those components below.
+- Promoting a new **Master**
+- Reconfiguring the other **Slaves** and make them point to the new **Master**
+- Announce the new **Master** to every other Sentinel peer
+- Reconfigure the old **Master** and demote to **Slave** when it comes back online
-### Redis setup
+You must have at least `3` Redis Sentinel servers, and they need to
+be each in a independent machine (that are believed to fail independently),
+ideally in different geographical areas.
-You must have at least 2 Redis servers: 1 Master, 1 or more Slaves.
-They should be configured the same way and with similar server specs, as
-in a failover situation, any Slave can be elected as the new Master by
-the Sentinel servers.
+You can configure them in the same machines where you've configured the other
+Redis servers, but understand that if a whole node goes down, you loose both
+a Sentinel and a Redis instance.
-In a minimal setup, the only required change for the slaves in `redis.conf`
-is the addition of a `slaveof` line pointing to the initial master.
-You can increase the security by defining a `requirepass` configuration in
-the master, and `masterauth` in slaves.
+The number of sentinels should ideally always be an **odd** number, for the
+consensus algorithm to be effective in the case of a failure.
----
+In a `3` nodes topology, you can only afford `1` Sentinel node going down.
+Whenever the **majority** of the Sentinels goes down, the network partition
+protection prevents destructive actions and a failover **will not be started**.
-**Configuring your own Redis server**
+Here are some examples:
-1. Add to the slaves' `redis.conf`:
+- With `5` or `6` sentinels, a maximum of `2` can go down for a failover begin.
+- With `7` sentinels, a maximum of `3` nodes can go down.
- ```conf
- # IP and port of the master Redis server
- slaveof 10.10.10.10 6379
- ```
+The **Leader** election can sometimes fail the voting round when **consensus**
+is not achieved (see the odd number of nodes requirement above). In that case,
+a new attempt will be made after the amount of time defined in
+`sentinel['failover_timeout']` (in milliseconds).
-1. Optionally, set up password authentication for increased security.
- Add the following to master's `redis.conf`:
+>**Note:**
+We will see where `sentinel['failover_timeout']` is defined later.
+
+The `failover_timeout` variable has a lot of different use cases. According to
+the official documentation:
+
+- The time needed to re-start a failover after a previous failover was
+ already tried against the same master by a given Sentinel, is two
+ times the failover timeout.
+
+- The time needed for a slave replicating to a wrong master according
+ to a Sentinel current configuration, to be forced to replicate
+ with the right master, is exactly the failover timeout (counting since
+ the moment a Sentinel detected the misconfiguration).
+
+- The time needed to cancel a failover that is already in progress but
+ did not produced any configuration change (SLAVEOF NO ONE yet not
+ acknowledged by the promoted slave).
+
+- The maximum time a failover in progress waits for all the slaves to be
+ reconfigured as slaves of the new master. However even after this time
+ the slaves will be reconfigured by the Sentinels anyway, but not with
+ the exact parallel-syncs progression as specified.
+
+### Available configuration setups
+
+Based on your infrastructure setup and how you have installed GitLab, there are
+multiple ways to configure Redis HA. Omnibus GitLab packages have Redis and/or
+Redis Sentinel bundled with them so you only need to focus on configuration.
+Pick the one that suits your needs.
+
+- [Installations from source][source]: You need to install Redis and Sentinel
+ yourself. Use the [Redis HA installation from source](redis_source.md)
+ documentation.
+- [Omnibus GitLab **Community Edition** (CE) package][ce]: Redis is bundled, so you
+ can use the package with only the Redis service enabled as described in steps
+ 1 and 2 of this document (works for both master and slave setups). To install
+ and configure Sentinel, jump directly to the Sentinel section in the
+ [Redis HA installation from source](redis_source.md#step-3-configuring-the-redis-sentinel-instances) documentation.
+- [Omnibus GitLab **Enterprise Edition** (EE) package][ee]: Both Redis and Sentinel
+ are bundled in the package, so you can use the EE package to setup the whole
+ Redis HA infrastructure (master, slave and Sentinel) which is described in
+ this document.
+- If you have installed GitLab using the Omnibus GitLab packages (CE or EE),
+ but you want to use your own external Redis server, follow steps 1-3 in the
+ [Redis HA installation from source](redis_source.md) documentation, then go
+ straight to step 4 in this guide to
+ [set up the GitLab application](#step-4-configuring-the-gitlab-application).
+
+## Configuring Redis HA
+
+This is the section where we install and setup the new Redis instances.
+
+>**Notes:**
+- We assume that you have installed GitLab and all HA components from scratch. If you
+ already have it installed and running, read how to
+ [switch from a single-machine installation to Redis HA](#switching-from-an-existing-single-machine-installation-to-redis-ha).
+- Redis nodes (both master and slaves) will need the same password defined in
+ `redis['password']`. At any time during a failover the Sentinels can
+ reconfigure a node and change its status from master to slave and vice versa.
+
+### Prerequisites
+
+The prerequisites for a HA Redis setup are the following:
+
+1. Provision the minimum required number of instances as specified in the
+ [recommended setup](#recommended-setup) section.
+1. We **Do not** recommend installing Redis or Redis Sentinel in the same machines your
+ GitLab application is running on as this weakens your HA configuration. You can however opt in to install Redis
+ and Sentinel in the same machine.
+1. All Redis nodes must be able to talk to each other and accept incoming
+ connections over Redis (`6379`) and Sentinel (`26379`) ports (unless you
+ change the default ones).
+1. The server that hosts the GitLab application must be able to access the
+ Redis nodes.
+1. Protect the nodes from access from external networks ([Internet][it]), using
+ firewall.
+
+### Step 1. Configuring the master Redis instance
+
+1. SSH into the **master** Redis server.
+1. [Download/install](https://about.gitlab.com/installation) the Omnibus GitLab
+ package you want using **steps 1 and 2** from the GitLab downloads page.
+ - Make sure you select the correct Omnibus package, with the same version
+ and type (Community, Enterprise editions) of your current install.
+ - Do not complete any other steps on the download page.
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
- ```conf
- # Optional password authentication for increased security
- requirepass "<password>"
+ ```ruby
+ # Enable the master role and disable all other services in the machine
+ # (you can still enable Sentinel).
+ redis_master_role['enable'] = true
+
+ # IP address pointing to a local IP that the other machines can reach to.
+ # You can also set bind to '0.0.0.0' which listen in all interfaces.
+ # If you really need to bind to an external accessible IP, make
+ # sure you add extra firewall rules to prevent unauthorized access.
+ redis['bind'] = '10.0.0.1'
+
+ # Define a port so Redis can listen for TCP requests which will allow other
+ # machines to connect to it.
+ redis['port'] = 6379
+
+ # Set up password authentication for Redis (use the same password in all nodes).
+ redis['password'] = 'redis-password-goes-here'
```
-1. Then add this line to all the slave servers' `redis.conf`:
+1. Only the primary GitLab application server should handle migrations. To
+ prevent database migrations from running on upgrade, add the following
+ configuration to your `/etc/gitlab/gitlab.rb` file:
- ```conf
- masterauth "<password>"
+ ```
+ gitlab_rails['auto_migrate'] = false
```
-1. Restart the Redis services for the changes to take effect.
+1. [Reconfigure Omnibus GitLab][reconfigure] for the changes to take effect.
----
+### Step 2. Configuring the slave Redis instances
-**Using Redis via Omnibus**
+1. SSH into the **slave** Redis server.
+1. [Download/install](https://about.gitlab.com/installation) the Omnibus GitLab
+ package you want using **steps 1 and 2** from the GitLab downloads page.
+ - Make sure you select the correct Omnibus package, with the same version
+ and type (Community, Enterprise editions) of your current install.
+ - Do not complete any other steps on the download page.
-1. Edit `/etc/gitlab/gitlab.rb` of a master Redis machine (usualy a single machine):
+1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- ## Redis TCP support (will disable UNIX socket transport)
- redis['bind'] = '0.0.0.0' # or specify an IP to bind to a single one
+ # Enable the slave role and disable all other services in the machine
+ # (you can still enable Sentinel). This will also set automatically
+ # `redis['master'] = false`.
+ redis_slave_role['enable'] = true
+
+ # IP address pointing to a local IP that the other machines can reach to.
+ # You can also set bind to '0.0.0.0' which listen in all interfaces.
+ # If you really need to bind to an external accessible IP, make
+ # sure you add extra firewall rules to prevent unauthorized access.
+ redis['bind'] = '10.0.0.2'
+
+ # Define a port so Redis can listen for TCP requests which will allow other
+ # machines to connect to it.
redis['port'] = 6379
- ## Master redis instance
- redis['password'] = '<huge password string here>'
- ```
+ # The same password for Redeis authentication you set up for the master node.
+ redis['password'] = 'redis-password-goes-here'
-1. Edit `/etc/gitlab/gitlab.rb` of a slave Redis machine (should be one or more machines):
+ # The IP of the master Redis node.
+ redis['master_ip'] = '10.0.0.1'
- ```ruby
- ## Redis TCP support (will disable UNIX socket transport)
- redis['bind'] = '0.0.0.0' # or specify an IP to bind to a single one
- redis['port'] = 6379
+ # Port of master Redis server, uncomment to change to non default. Defaults
+ # to `6379`.
+ #redis['master_port'] = 6379
+ ```
- ## Slave redis instance
- redis['master_ip'] = '10.10.10.10' # IP of master Redis server
- redis['master_port'] = 6379 # Port of master Redis server
- redis['master_password'] = "<huge password string here>"
+1. To prevent database migrations from running on upgrade, run:
+
+ ```
+ sudo touch /etc/gitlab/skip-auto-migrations
```
-1. Reconfigure the GitLab for the changes to take effect: `sudo gitlab-ctl reconfigure`
+ Only the primary GitLab application server should handle migrations.
+
+1. [Reconfigure Omnibus GitLab][reconfigure] for the changes to take effect.
+1. Go through the steps again for all the other slave nodes.
---
+These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after
+a failover, as the nodes will be managed by the Sentinels, and even after a
+`gitlab-ctl reconfigure`, they will get their configuration restored by
+the same Sentinels.
+
+### Step 3. Configuring the Redis Sentinel instances
+
+>**Note:**
+Redis Sentinel is bundled with Omnibus GitLab Enterprise Edition only. The
+following section assumes you are using Omnibus GitLab Enterprise Edition.
+For the Omnibus Community Edition and installations from source, follow the
+[Redis HA source install](redis_source.md) guide.
+
Now that the Redis servers are all set up, let's configure the Sentinel
servers.
-### Sentinel setup
+If you are not sure if your Redis servers are working and replicating
+correctly, please read the [Troubleshooting Replication](#troubleshooting-replication)
+and fix it before proceeding with Sentinel setup.
-We don't provide yet an automated way to setup and run the Sentinel daemon
-from Omnibus installation method. You must follow the instructions below and
-run it by yourself.
+You must have at least `3` Redis Sentinel servers, and they need to
+be each in an independent machine. You can configure them in the same
+machines where you've configured the other Redis servers.
-The support for Sentinel in Ruby has some [caveats](https://github.com/redis/redis-rb/issues/531).
-While you can give any name for the `master-group-name` part of the
-configuration, as in this example:
+With GitLab Enterprise Edition, you can use the Omnibus package to setup
+multiple machines with the Sentinel daemon.
-```conf
-sentinel monitor <master-group-name> <ip> <port> <quorum>
-```
+---
-,for it to work in Ruby, you have to use the "hostname" of the master Redis
-server, otherwise you will get an error message like:
-`Redis::CannotConnectError: No sentinels available.`. Read
-[Sentinel troubleshooting](#sentinel-troubleshooting) for more information.
+1. SSH into the server that will host Redis Sentinel.
+1. **You can omit this step if the Sentinels will be hosted in the same node as
+ the other Redis instances.**
-Here is an example configuration file (`sentinel.conf`) for a Sentinel node:
+ [Download/install](https://about.gitlab.com/downloads-ee) the
+ Omnibus GitLab Enterprise Edition package using **steps 1 and 2** from the
+ GitLab downloads page.
+ - Make sure you select the correct Omnibus package, with the same version
+ the GitLab application is running.
+ - Do not complete any other steps on the download page.
-```conf
-port 26379
-sentinel monitor master-redis.example.com 10.10.10.10 6379 1
-sentinel down-after-milliseconds master-redis.example.com 10000
-sentinel config-epoch master-redis.example.com 0
-sentinel leader-epoch master-redis.example.com 0
-```
+1. Edit `/etc/gitlab/gitlab.rb` and add the contents (if you are installing the
+ Sentinels in the same node as the other Redis instances, some values might
+ be duplicate below):
----
+ ```ruby
+ redis_sentinel_role['enable'] = true
-The final part is to inform the main GitLab application server of the Redis
-master and the new sentinels servers.
+ # Must be the same in every sentinel node
+ redis['master_name'] = 'gitlab-redis'
-### GitLab setup
+ # The same password for Redis authentication you set up for the master node.
+ redis['password'] = 'redis-password-goes-here'
-You can enable or disable sentinel support at any time in new or existing
-installations. From the GitLab application perspective, all it requires is
-the correct credentials for the master Redis and for a few Sentinel nodes.
+ # The IP of the master Redis node.
+ redis['master_ip'] = '10.0.0.1'
-It doesn't require a list of all Sentinel nodes, as in case of a failure,
-the application will need to query only one of them.
+ # Define a port so Redis can listen for TCP requests which will allow other
+ # machines to connect to it.
+ redis['port'] = 6379
->**Note:**
-The following steps should be performed in the [GitLab application server](gitlab.md).
+ # Port of master Redis server, uncomment to change to non default. Defaults
+ # to `6379`.
+ #redis['master_port'] = 6379
+
+ ## Configure Sentinel
+ sentinel['bind'] = '10.0.0.1'
+
+ # Port that Sentinel listens on, uncomment to change to non default. Defaults
+ # to `26379`.
+ # sentinel['port'] = 26379
+
+ ## Quorum must reflect the amount of voting sentinels it take to start a failover.
+ ## Value must NOT be greater then the amount of sentinels.
+ ##
+ ## The quorum can be used to tune Sentinel in two ways:
+ ## 1. If a the quorum is set to a value smaller than the majority of Sentinels
+ ## we deploy, we are basically making Sentinel more sensible to master failures,
+ ## triggering a failover as soon as even just a minority of Sentinels is no longer
+ ## able to talk with the master.
+ ## 1. If a quorum is set to a value greater than the majority of Sentinels, we are
+ ## making Sentinel able to failover only when there are a very large number (larger
+ ## than majority) of well connected Sentinels which agree about the master being down.s
+ sentinel['quorum'] = 2
+
+ ## Consider unresponsive server down after x amount of ms.
+ # sentinel['down_after_milliseconds'] = 10000
+
+ ## Specifies the failover timeout in milliseconds. It is used in many ways:
+ ##
+ ## - The time needed to re-start a failover after a previous failover was
+ ## already tried against the same master by a given Sentinel, is two
+ ## times the failover timeout.
+ ##
+ ## - The time needed for a slave replicating to a wrong master according
+ ## to a Sentinel current configuration, to be forced to replicate
+ ## with the right master, is exactly the failover timeout (counting since
+ ## the moment a Sentinel detected the misconfiguration).
+ ##
+ ## - The time needed to cancel a failover that is already in progress but
+ ## did not produced any configuration change (SLAVEOF NO ONE yet not
+ ## acknowledged by the promoted slave).
+ ##
+ ## - The maximum time a failover in progress waits for all the slaves to be
+ ## reconfigured as slaves of the new master. However even after this time
+ ## the slaves will be reconfigured by the Sentinels anyway, but not with
+ ## the exact parallel-syncs progression as specified.
+ # sentinel['failover_timeout'] = 60000
+ ```
-**For source based installations**
+1. To prevent database migrations from running on upgrade, run:
-1. Edit `/home/git/gitlab/config/resque.yml` following the example in
- `/home/git/gitlab/config/resque.yml.example`, and uncomment the sentinels
- line, changing to the correct server credentials.
-1. Restart GitLab for the changes to take effect.
+ ```
+ sudo touch /etc/gitlab/skip-auto-migrations
+ ```
-**For Omnibus installations**
+ Only the primary GitLab application server should handle migrations.
+1. [Reconfigure Omnibus GitLab][reconfigure] for the changes to take effect.
+1. Go through the steps again for all the other Sentinel nodes.
+
+### Step 4. Configuring the GitLab application
+
+The final part is to inform the main GitLab application server of the Redis
+Sentinels servers and authentication credentials.
+
+You can enable or disable Sentinel support at any time in new or existing
+installations. From the GitLab application perspective, all it requires is
+the correct credentials for the Sentinel nodes.
+
+While it doesn't require a list of all Sentinel nodes, in case of a failure,
+it needs to access at least one of the listed.
+
+>**Note:**
+The following steps should be performed in the [GitLab application server](gitlab.md)
+which ideally should not have Redis or Sentinels on it for a HA setup.
+
+1. SSH into the server where the GitLab application is installed.
1. Edit `/etc/gitlab/gitlab.rb` and add/change the following lines:
- ```ruby
- gitlab-rails['redis_host'] = "master-redis.example.com"
- gitlab-rails['redis_port'] = 6379
- gitlab-rails['redis_password'] = '<huge password string here>'
- gitlab-rails['redis_sentinels'] = [
- {'host' => '10.10.10.1', 'port' => 26379},
- {'host' => '10.10.10.2', 'port' => 26379},
- {'host' => '10.10.10.3', 'port' => 26379}
+ ```
+ ## Must be the same in every sentinel node
+ redis['master_name'] = 'gitlab-redis'
+
+ ## The same password for Redis authentication you set up for the master node.
+ redis['master_password'] = 'redis-password-goes-here'
+
+ ## A list of sentinels with `host` and `port`
+ gitlab_rails['redis_sentinels'] = [
+ {'host' => '10.0.0.1', 'port' => 26379},
+ {'host' => '10.0.0.2', 'port' => 26379},
+ {'host' => '10.0.0.3', 'port' => 26379}
]
```
-1. [Reconfigure] the GitLab for the changes to take effect.
+1. [Reconfigure Omnibus GitLab][reconfigure] for the changes to take effect.
-### Sentinel troubleshooting
+## Switching from an existing single-machine installation to Redis HA
-If you get an error like: `Redis::CannotConnectError: No sentinels available.`,
-there may be something wrong with your configuration files or it can be related
-to [this issue][gh-531] ([pull request][gh-534] that should make things better).
+If you already have a single-machine GitLab install running, you will need to
+replicate from this machine first, before de-activating the Redis instance
+inside it.
+
+Your single-machine install will be the initial **Master**, and the `3` others
+should be configured as **Slave** pointing to this machine.
+
+After replication catches up, you will need to stop services in the
+single-machine install, to rotate the **Master** to one of the new nodes.
-It's a bit rigid the way you have to config `resque.yml` and `sentinel.conf`,
-otherwise `redis-rb` will not work properly.
+Make the required changes in configuration and restart the new nodes again.
-The hostname ('my-primary-redis') of the primary Redis server (`sentinel.conf`)
-**must** match the one configured in GitLab (`resque.yml` for source installations
-or `gitlab-rails['redis_*']` in Omnibus) and it must be valid ex:
+To disable redis in the single install, edit `/etc/gitlab/gitlab.rb`:
-```conf
-# sentinel.conf:
-sentinel monitor my-primary-redis 10.10.10.10 6379 1
-sentinel down-after-milliseconds my-primary-redis 10000
-sentinel config-epoch my-primary-redis 0
-sentinel leader-epoch my-primary-redis 0
+```ruby
+redis['enable'] = false
```
-```yaml
-# resque.yaml
-production:
- url: redis://my-primary-redis:6378
- sentinels:
- -
- host: slave1
- port: 26380 # point to sentinel, not to redis port
- -
- host: slave2
- port: 26381 # point to sentinel, not to redis port
+If you fail to replicate first, you may loose data (unprocessed background jobs).
+
+## Example of a minimal configuration with 1 master, 2 slaves and 3 Sentinels
+
+>**Note:**
+Redis Sentinel is bundled with Omnibus GitLab Enterprise Edition only. For
+different setups, read the
+[available configuration setups](#available-configuration-setups) section.
+
+In this example we consider that all servers have an internal network
+interface with IPs in the `10.0.0.x` range, and that they can connect
+to each other using these IPs.
+
+In a real world usage, you would also setup firewall rules to prevent
+unauthorized access from other machines and block traffic from the
+outside (Internet).
+
+We will use the same `3` nodes with **Redis** + **Sentinel** topology
+discussed in [Redis setup overview](#redis-setup-overview) and
+[Sentinel setup overview](#sentinel-setup-overview) documentation.
+
+Here is a list and description of each **machine** and the assigned **IP**:
+
+* `10.0.0.1`: Redis Master + Sentinel 1
+* `10.0.0.2`: Redis Slave 1 + Sentinel 2
+* `10.0.0.3`: Redis Slave 2 + Sentinel 3
+* `10.0.0.4`: GitLab application
+
+Please note that after the initial configuration, if a failover is initiated
+by the Sentinel nodes, the Redis nodes will be reconfigured and the **Master**
+will change permanently (including in `redis.conf`) from one node to the other,
+until a new failover is initiated again.
+
+The same thing will happen with `sentinel.conf` that will be overridden after the
+initial execution, after any new sentinel node starts watching the **Master**,
+or a failover promotes a different **Master** node.
+
+### Example configuration for Redis master and Sentinel 1
+
+In `/etc/gitlab/gitlab.rb`:
+
+```ruby
+redis_master_role['enable'] = true
+redis_sentinel_role['enable'] = true
+redis['bind'] = '10.0.0.1'
+redis['port'] = 6379
+redis['password'] = 'redis-password-goes-here'
+redis['master_name'] = 'gitlab-redis' # must be the same in every sentinel node
+redis['master_password'] = 'redis-password-goes-here' # the same value defined in redis['password'] in the master instance
+redis['master_ip'] = '10.0.0.1' # ip of the initial master redis instance
+#redis['master_port'] = 6379 # port of the initial master redis instance, uncomment to change to non default
+sentinel['bind'] = '10.0.0.1'
+# sentinel['port'] = 26379 # uncomment to change default port
+sentinel['quorum'] = 2
+# sentinel['down_after_milliseconds'] = 10000
+# sentinel['failover_timeout'] = 60000
+```
+
+[Reconfigure Omnibus GitLab][reconfigure] for the changes to take effect.
+
+### Example configuration for Redis slave 1 and Sentinel 2
+
+In `/etc/gitlab/gitlab.rb`:
+
+```ruby
+redis_slave_role['enable'] = true
+redis_sentinel_role['enable'] = true
+redis['bind'] = '10.0.0.2'
+redis['port'] = 6379
+redis['password'] = 'redis-password-goes-here'
+redis['master_password'] = 'redis-password-goes-here'
+redis['master_ip'] = '10.0.0.1' # IP of master Redis server
+#redis['master_port'] = 6379 # Port of master Redis server, uncomment to change to non default
+redis['master_name'] = 'gitlab-redis' # must be the same in every sentinel node
+sentinel['bind'] = '10.0.0.2'
+# sentinel['port'] = 26379 # uncomment to change default port
+sentinel['quorum'] = 2
+# sentinel['down_after_milliseconds'] = 10000
+# sentinel['failover_timeout'] = 60000
+```
+
+[Reconfigure Omnibus GitLab][reconfigure] for the changes to take effect.
+
+### Example configuration for Redis slave 2 and Sentinel 3
+
+In `/etc/gitlab/gitlab.rb`:
+
+```ruby
+redis_slave_role['enable'] = true
+redis_sentinel_role['enable'] = true
+redis['bind'] = '10.0.0.3'
+redis['port'] = 6379
+redis['password'] = 'redis-password-goes-here'
+redis['master_password'] = 'redis-password-goes-here'
+redis['master_ip'] = '10.0.0.1' # IP of master Redis server
+#redis['master_port'] = 6379 # Port of master Redis server, uncomment to change to non default
+redis['master_name'] = 'gitlab-redis' # must be the same in every sentinel node
+sentinel['bind'] = '10.0.0.3'
+# sentinel['port'] = 26379 # uncomment to change default port
+sentinel['quorum'] = 2
+# sentinel['down_after_milliseconds'] = 10000
+# sentinel['failover_timeout'] = 60000
```
-When in doubt, please read [Redis Sentinel documentation](http://redis.io/topics/sentinel)
+[Reconfigure Omnibus GitLab][reconfigure] for the changes to take effect.
+
+### Example configuration for the GitLab application
+
+In `/etc/gitlab/gitlab.rb`:
+
+```ruby
+redis['master_name'] = 'gitlab-redis'
+redis['password'] = 'redis-password-goes-here'
+gitlab_rails['redis_sentinels'] = [
+ {'host' => '10.0.0.1', 'port' => 26379},
+ {'host' => '10.0.0.2', 'port' => 26379},
+ {'host' => '10.0.0.3', 'port' => 26379}
+]
+```
+
+[Reconfigure Omnibus GitLab][reconfigure] for the changes to take effect.
+
+## Advanced configuration
+
+Omnibus GitLab configures some things behind the curtains to make the sysadmins'
+lives easier. If you want to know what happens underneath keep reading.
+
+### Control running services
+
+In the previous example, we've used `redis_sentinel_role` and
+`redis_master_role` which simplifies the amount of configuration changes.
+
+If you want more control, here is what each one sets for you automatically
+when enabled:
+
+```ruby
+## Redis Sentinel Role
+redis_sentinel_role['enable'] = true
+
+# When Sentinel Role is enabled, the following services are also enabled
+sentinel['enable'] = true
+
+# The following services are disabled
+redis['enable'] = false
+bootstrap['enable'] = false
+nginx['enable'] = false
+postgresql['enable'] = false
+gitlab_rails['enable'] = false
+mailroom['enable'] = false
+
+-------
+
+## Redis master/slave Role
+redis_master_role['enable'] = true # enable only one of them
+redis_slave_role['enable'] = true # enable only one of them
+
+# When Redis Master or Slave role are enabled, the following services are
+# enabled/disabled. Note that if Redis and Sentinel roles are combined, both
+# services will be enabled.
+
+# The following services are disabled
+sentinel['enable'] = false
+bootstrap['enable'] = false
+nginx['enable'] = false
+postgresql['enable'] = false
+gitlab_rails['enable'] = false
+mailroom['enable'] = false
+
+# For Redis Slave role, also change this setting from default 'true' to 'false':
+redis['master'] = false
+```
+
+You can find the relevant attributes defined in [gitlab_rails.rb][omnifile].
+
+## Troubleshooting
+
+There are a lot of moving parts that needs to be taken care carefully
+in order for the HA setup to work as expected.
+
+Before proceeding with the troubleshooting below, check your firewall rules:
+
+- Redis machines
+ - Accept TCP connection in `6379`
+ - Connect to the other Redis machines via TCP in `6379`
+- Sentinel machines
+ - Accept TCP connection in `26379`
+ - Connect to other Sentinel machines via TCP in `26379`
+ - Connect to the Redis machines via TCP in `6379`
+
+### Troubleshooting Redis replication
+
+You can check if everything is correct by connecting to each server using
+`redis-cli` application, and sending the `INFO` command.
+
+If authentication was correctly defined, it should fail with:
+`NOAUTH Authentication required` error. Try to authenticate with the
+previous defined password with `AUTH redis-password-goes-here` and
+try the `INFO` command again.
+
+Look for the `# Replication` section where you should see some important
+information like the `role` of the server.
+
+When connected to a `master` redis, you will see the number of connected
+`slaves`, and a list of each with connection details:
+
+```
+# Replication
+role:master
+connected_slaves:1
+slave0:ip=10.133.5.21,port=6379,state=online,offset=208037514,lag=1
+master_repl_offset:208037658
+repl_backlog_active:1
+repl_backlog_size:1048576
+repl_backlog_first_byte_offset:206989083
+repl_backlog_histlen:1048576
+```
+
+When it's a `slave`, you will see details of the master connection and if
+its `up` or `down`:
+
+```
+# Replication
+role:slave
+master_host:10.133.1.58
+master_port:6379
+master_link_status:up
+master_last_io_seconds_ago:1
+master_sync_in_progress:0
+slave_repl_offset:208096498
+slave_priority:100
+slave_read_only:1
+connected_slaves:0
+master_repl_offset:0
+repl_backlog_active:0
+repl_backlog_size:1048576
+repl_backlog_first_byte_offset:0
+repl_backlog_histlen:0
+```
+
+### Troubleshooting Sentinel
+
+If you get an error like: `Redis::CannotConnectError: No sentinels available.`,
+there may be something wrong with your configuration files or it can be related
+to [this issue][gh-531].
+
+You must make sure you are defining the same value in `redis['master_name']`
+and `redis['master_pasword']` as you defined for your sentinel node.
+
+The way the redis connector `redis-rb` works with sentinel is a bit
+non-intuitive. We try to hide the complexity in omnibus, but it still requires
+a few extra configs.
---
@@ -273,7 +787,7 @@ To make sure your configuration is correct:
sudo gitlab-rails console
# For source installations
- sudo -u git rails console RAILS_ENV=production
+ sudo -u git rails console production
```
1. Run in the console:
@@ -288,8 +802,8 @@ To make sure your configuration is correct:
1. To simulate a failover on master Redis, SSH into the Redis server and run:
```bash
- # port must match your master redis port
- redis-cli -h localhost -p 6379 DEBUG sleep 60
+ # port must match your master redis port, and the sleep time must be a few seconds bigger than defined one
+ redis-cli -h localhost -p 6379 DEBUG sleep 20
```
1. Then back in the Rails console from the first step, run:
@@ -301,10 +815,26 @@ To make sure your configuration is correct:
You should see a different port after a few seconds delay
(the failover/reconnect time).
----
-Read more on high-availability configuration:
+## Changelog
+
+Changes to Redis HA over time.
+
+**8.14**
+
+- Redis Sentinel support is production-ready and bundled in the Omnibus GitLab
+ Enterprise Edition package
+- Documentation restructure for better readability
+
+**8.11**
+
+- Experimental Redis Sentinel support was added
+
+## Further reading
+
+Read more on High Availability:
+1. [High Availability Overview](README.md)
1. [Configure the database](database.md)
1. [Configure NFS](nfs.md)
1. [Configure the GitLab application servers](gitlab.md)
@@ -315,3 +845,10 @@ Read more on high-availability configuration:
[reconfigure]: ../restart_gitlab.md#omnibus-gitlab-reconfigure
[gh-531]: https://github.com/redis/redis-rb/issues/531
[gh-534]: https://github.com/redis/redis-rb/issues/534
+[redis]: http://redis.io/
+[sentinel]: http://redis.io/topics/sentinel
+[omnifile]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/libraries/gitlab_rails.rb
+[source]: ../../install/installation.md
+[ce]: https://about.gitlab.com/downloads
+[ee]: https://about.gitlab.com/downloads-ee
+[it]: https://gitlab.com/gitlab-org/gitlab-ce/uploads/c4cc8cd353604bd80315f9384035ff9e/The_Internet_IT_Crowd.png
diff --git a/doc/administration/high_availability/redis_source.md b/doc/administration/high_availability/redis_source.md
new file mode 100644
index 00000000000..fe982ea83c2
--- /dev/null
+++ b/doc/administration/high_availability/redis_source.md
@@ -0,0 +1,367 @@
+# Configuring non-Omnibus Redis for GitLab HA
+
+This is the documentation for configuring a Highly Available Redis setup when
+you have installed Redis all by yourself and not using the bundled one that
+comes with the Omnibus packages.
+
+We cannot stress enough the importance of reading the
+[Overview section](redis.md#overview) of the Omnibus Redis HA as it provides
+some invaluable information to the configuration of Redis. Please proceed to
+read it before going forward with this guide.
+
+We also highly recommend that you use the Omnibus GitLab packages, as we
+optimize them specifically for GitLab, and we will take care of upgrading Redis
+to the latest supported version.
+
+If you're not sure whether this guide is for you, please refer to
+[Available configuration setups](redis.md#available-configuration-setups) in
+the Omnibus Redis HA documentation.
+
+## Configuring your own Redis server
+
+This is the section where we install and setup the new Redis instances.
+
+### Prerequisites
+
+- All Redis servers in this guide must be configured to use a TCP connection
+ instead of a socket. To configure Redis to use TCP connections you need to
+ define both `bind` and `port` in the Redis config file. You can bind to all
+ interfaces (`0.0.0.0`) or specify the IP of the desired interface
+ (e.g., one from an internal network).
+- Since Redis 3.2, you must define a password to receive external connections
+ (`requirepass`).
+- If you are using Redis with Sentinel, you will also need to define the same
+ password for the slave password definition (`masterauth`) in the same instance.
+
+In addition, read the prerequisites as described in the
+[Omnibus Redis HA document](redis.md#prerequisites) since they provide some
+valuable information for the general setup.
+
+### Step 1. Configuring the master Redis instance
+
+Assuming that the Redis master instance IP is `10.0.0.1`:
+
+1. [Install Redis](../../install/installation.md#6-redis)
+1. Edit `/etc/redis/redis.conf`:
+
+ ```conf
+ ## Define a `bind` address pointing to a local IP that your other machines
+ ## can reach you. If you really need to bind to an external accessible IP, make
+ ## sure you add extra firewall rules to prevent unauthorized access:
+ bind 10.0.0.1
+
+ ## Define a `port` to force redis to listen on TCP so other machines can
+ ## connect to it (default port is `6379`).
+ port 6379
+
+ ## Set up password authentication (use the same password in all nodes).
+ ## The password should be defined equal for both `requirepass` and `masterauth`
+ ## when setting up Redis to use with Sentinel.
+ requirepass redis-password-goes-here
+ masterauth redis-password-goes-here
+ ```
+
+1. Restart the Redis service for the changes to take effect.
+
+### Step 2. Configuring the slave Redis instances
+
+Assuming that the Redis slave instance IP is `10.0.0.2`:
+
+1. [Install Redis](../../install/installation.md#6-redis)
+1. Edit `/etc/redis/redis.conf`:
+
+ ```conf
+ ## Define a `bind` address pointing to a local IP that your other machines
+ ## can reach you. If you really need to bind to an external accessible IP, make
+ ## sure you add extra firewall rules to prevent unauthorized access:
+ bind 10.0.0.2
+
+ ## Define a `port` to force redis to listen on TCP so other machines can
+ ## connect to it (default port is `6379`).
+ port 6379
+
+ ## Set up password authentication (use the same password in all nodes).
+ ## The password should be defined equal for both `requirepass` and `masterauth`
+ ## when setting up Redis to use with Sentinel.
+ requirepass redis-password-goes-here
+ masterauth redis-password-goes-here
+
+ ## Define `slaveof` pointing to the Redis master instance with IP and port.
+ slaveof 10.0.0.1 6379
+ ```
+
+1. Restart the Redis service for the changes to take effect.
+1. Go through the steps again for all the other slave nodes.
+
+### Step 3. Configuring the Redis Sentinel instances
+
+Sentinel is a special type of Redis server. It inherits most of the basic
+configuration options you can define in `redis.conf`, with specific ones
+starting with `sentinel` prefix.
+
+Assuming that the Redis Sentinel is installed on the same instance as Redis
+master with IP `10.0.0.1` (some settings might overlap with the master):
+
+1. [Install Redis Sentinel](http://redis.io/topics/sentinel)
+1. Edit `/etc/redis/sentinel.conf`:
+
+ ```conf
+ ## Define a `bind` address pointing to a local IP that your other machines
+ ## can reach you. If you really need to bind to an external accessible IP, make
+ ## sure you add extra firewall rules to prevent unauthorized access:
+ bind 10.0.0.1
+
+ ## Define a `port` to force Sentinel to listen on TCP so other machines can
+ ## connect to it (default port is `6379`).
+ port 26379
+
+ ## Set up password authentication (use the same password in all nodes).
+ ## The password should be defined equal for both `requirepass` and `masterauth`
+ ## when setting up Redis to use with Sentinel.
+ requirepass redis-password-goes-here
+ masterauth redis-password-goes-here
+
+ ## Define with `sentinel auth-pass` the same shared password you have
+ ## defined for both Redis master and slaves instances.
+ sentinel auth-pass gitlab-redis redis-password-goes-here
+
+ ## Define with `sentinel monitor` the IP and port of the Redis
+ ## master node, and the quorum required to start a failover.
+ sentinel monitor gitlab-redis 10.0.0.1 6379 2
+
+ ## Define with `sentinel down-after-milliseconds` the time in `ms`
+ ## that an unresponsive server will be considered down.
+ sentinel down-after-milliseconds gitlab-redis 10000
+
+ ## Define a value for `sentinel failover_timeout` in `ms`. This has multiple
+ ## meanings:
+ ##
+ ## * The time needed to re-start a failover after a previous failover was
+ ## already tried against the same master by a given Sentinel, is two
+ ## times the failover timeout.
+ ##
+ ## * The time needed for a slave replicating to a wrong master according
+ ## to a Sentinel current configuration, to be forced to replicate
+ ## with the right master, is exactly the failover timeout (counting since
+ ## the moment a Sentinel detected the misconfiguration).
+ ##
+ ## * The time needed to cancel a failover that is already in progress but
+ ## did not produced any configuration change (SLAVEOF NO ONE yet not
+ ## acknowledged by the promoted slave).
+ ##
+ ## * The maximum time a failover in progress waits for all the slaves to be
+ ## reconfigured as slaves of the new master. However even after this time
+ ## the slaves will be reconfigured by the Sentinels anyway, but not with
+ ## the exact parallel-syncs progression as specified.
+ sentinel failover_timeout 30000
+ ```
+1. Restart the Redis service for the changes to take effect.
+1. Go through the steps again for all the other Sentinel nodes.
+
+### Step 4. Configuring the GitLab application
+
+You can enable or disable Sentinel support at any time in new or existing
+installations. From the GitLab application perspective, all it requires is
+the correct credentials for the Sentinel nodes.
+
+While it doesn't require a list of all Sentinel nodes, in case of a failure,
+it needs to access at least one of listed ones.
+
+The following steps should be performed in the [GitLab application server](gitlab.md)
+which ideally should not have Redis or Sentinels in the same machine for a HA
+setup:
+
+1. Edit `/home/git/gitlab/config/resque.yml` following the example in
+ [resque.yml.example][resque], and uncomment the Sentinel lines, pointing to
+ the correct server credentials:
+
+ ```yaml
+ # resque.yaml
+ production:
+ url: redis://:redi-password-goes-here@gitlab-redis/
+ sentinels:
+ -
+ host: 10.0.0.1
+ port: 26379 # point to sentinel, not to redis port
+ -
+ host: 10.0.0.2
+ port: 26379 # point to sentinel, not to redis port
+ -
+ host: 10.0.0.3
+ port: 26379 # point to sentinel, not to redis port
+ ```
+
+1. [Restart GitLab][restart] for the changes to take effect.
+
+## Example of minimal configuration with 1 master, 2 slaves and 3 Sentinels
+
+In this example we consider that all servers have an internal network
+interface with IPs in the `10.0.0.x` range, and that they can connect
+to each other using these IPs.
+
+In a real world usage, you would also setup firewall rules to prevent
+unauthorized access from other machines, and block traffic from the
+outside ([Internet][it]).
+
+For this example, **Sentinel 1** will be configured in the same machine as the
+**Redis Master**, **Sentinel 2** and **Sentinel 3** in the same machines as the
+**Slave 1** and **Slave 2** respectively.
+
+Here is a list and description of each **machine** and the assigned **IP**:
+
+* `10.0.0.1`: Redis Master + Sentinel 1
+* `10.0.0.2`: Redis Slave 1 + Sentinel 2
+* `10.0.0.3`: Redis Slave 2 + Sentinel 3
+* `10.0.0.4`: GitLab application
+
+Please note that after the initial configuration, if a failover is initiated
+by the Sentinel nodes, the Redis nodes will be reconfigured and the **Master**
+will change permanently (including in `redis.conf`) from one node to the other,
+until a new failover is initiated again.
+
+The same thing will happen with `sentinel.conf` that will be overridden after the
+initial execution, after any new sentinel node starts watching the **Master**,
+or a failover promotes a different **Master** node.
+
+### Example configuration for Redis master and Sentinel 1
+
+1. In `/etc/redis/redis.conf`:
+
+ ```conf
+ bind 10.0.0.1
+ port 6379
+ requirepass redis-password-goes-here
+ masterauth redis-password-goes-here
+ ```
+
+1. In `/etc/redis/sentinel.conf`:
+
+ ```conf
+ bind 10.0.0.1
+ port 26379
+ sentinel auth-pass gitlab-redis redis-password-goes-here
+ sentinel monitor gitlab-redis 10.0.0.1 6379 2
+ sentinel down-after-milliseconds gitlab-redis 10000
+ sentinel failover_timeout 30000
+ ```
+
+1. Restart the Redis service for the changes to take effect.
+
+### Example configuration for Redis slave 1 and Sentinel 2
+
+1. In `/etc/redis/redis.conf`:
+
+ ```conf
+ bind 10.0.0.2
+ port 6379
+ requirepass redis-password-goes-here
+ masterauth redis-password-goes-here
+ slaveof 10.0.0.1 6379
+ ```
+
+1. In `/etc/redis/sentinel.conf`:
+
+ ```conf
+ bind 10.0.0.2
+ port 26379
+ sentinel auth-pass gitlab-redis redis-password-goes-here
+ sentinel monitor gitlab-redis 10.0.0.1 6379 2
+ sentinel down-after-milliseconds gitlab-redis 10000
+ sentinel failover_timeout 30000
+ ```
+
+1. Restart the Redis service for the changes to take effect.
+
+### Example configuration for Redis slave 2 and Sentinel 3
+
+1. In `/etc/redis/redis.conf`:
+
+ ```conf
+ bind 10.0.0.3
+ port 6379
+ requirepass redis-password-goes-here
+ masterauth redis-password-goes-here
+ slaveof 10.0.0.1 6379
+ ```
+
+1. In `/etc/redis/sentinel.conf`:
+
+ ```conf
+ bind 10.0.0.3
+ port 26379
+ sentinel auth-pass gitlab-redis redis-password-goes-here
+ sentinel monitor gitlab-redis 10.0.0.1 6379 2
+ sentinel down-after-milliseconds gitlab-redis 10000
+ sentinel failover_timeout 30000
+ ```
+
+1. Restart the Redis service for the changes to take effect.
+
+### Example configuration of the GitLab application
+
+1. Edit `/home/git/gitlab/config/resque.yml`:
+
+ ```yaml
+ production:
+ url: redis://:redi-password-goes-here@gitlab-redis/
+ sentinels:
+ -
+ host: 10.0.0.1
+ port: 26379 # point to sentinel, not to redis port
+ -
+ host: 10.0.0.2
+ port: 26379 # point to sentinel, not to redis port
+ -
+ host: 10.0.0.3
+ port: 26379 # point to sentinel, not to redis port
+ ```
+
+1. [Restart GitLab][restart] for the changes to take effect.
+
+## Troubleshooting
+
+We have a more detailed [Troubleshooting](redis.md#troubleshooting) explained
+in the documentation for Omnibus GitLab installations. Here we will list only
+the things that are specific to a source installation.
+
+If you get an error in GitLab like `Redis::CannotConnectError: No sentinels available.`,
+there may be something wrong with your configuration files or it can be related
+to [this upstream issue][gh-531].
+
+You must make sure that `resque.yml` and `sentinel.conf` are configured correctly,
+otherwise `redis-rb` will not work properly.
+
+The `master-group-name` ('gitlab-redis') defined in (`sentinel.conf`)
+**must** be used as the hostname in GitLab (`resque.yml`):
+
+```conf
+# sentinel.conf:
+sentinel monitor gitlab-redis 10.0.0.1 6379 2
+sentinel down-after-milliseconds gitlab-redis 10000
+sentinel config-epoch gitlab-redis 0
+sentinel leader-epoch gitlab-redis 0
+```
+
+```yaml
+# resque.yaml
+production:
+ url: redis://:myredispassword@gitlab-redis/
+ sentinels:
+ -
+ host: 10.0.0.1
+ port: 26379 # point to sentinel, not to redis port
+ -
+ host: 10.0.0.2
+ port: 26379 # point to sentinel, not to redis port
+ -
+ host: 10.0.0.3
+ port: 26379 # point to sentinel, not to redis port
+```
+
+When in doubt, please read [Redis Sentinel documentation](http://redis.io/topics/sentinel).
+
+[gh-531]: https://github.com/redis/redis-rb/issues/531
+[downloads]: https://about.gitlab.com/downloads
+[restart]: ../restart_gitlab.md#installations-from-source
+[it]: https://gitlab.com/gitlab-org/gitlab-ce/uploads/c4cc8cd353604bd80315f9384035ff9e/The_Internet_IT_Crowd.png
+[resque]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/resque.yml.example
diff --git a/doc/administration/housekeeping.md b/doc/administration/housekeeping.md
index ad1fa98b63b..bb621b788f1 100644
--- a/doc/administration/housekeeping.md
+++ b/doc/administration/housekeeping.md
@@ -3,14 +3,33 @@
> [Introduced][ce-2371] in GitLab 8.4.
---
+## Automatic housekeeping
-The housekeeping function runs `git gc` ([man page][man]) on the current
-project Git repository.
+GitLab automatically runs `git gc` and `git repack` on repositories
+after Git pushes. If needed you can change how often this happens, or
+to turn it off, go to **Admin area > Settings**
+(`/admin/application_settings`).
-`git gc` runs a number of housekeeping tasks, such as compressing file
-revisions (to reduce disk space and increase performance) and removing
-unreachable objects which may have been created from prior invocations of
-`git add`.
+## Manual housekeeping
+
+The housekeeping function will run a `repack` or `gc` depending on the
+"Automatic Git repository housekeeping" settings configured in **Admin area > Settings**
+
+For example in the following scenario a `git repack -d` will be executed:
+
++ Project: pushes since gc counter (`pushes_since_gc`) = `10`
++ Git GC period = `200`
++ Full repack period = `50`
+
+When the `pushes_since_gc` value is 50 a `repack -A -d --pack-kept-objects` will run, similarly when
+the `pushes_since_gc` value is 200 a `git gc` will be run.
+
++ `git gc` ([man page][man-gc]) runs a number of housekeeping tasks,
+such as compressing filerevisions (to reduce disk space and increase performance)
+and removing unreachable objects which may have been created from prior invocations of
+`git add`.
+
++ `git repack` ([man page][man-repack]) re-organize existing packs into a single, more efficient pack.
You can find this option under your **[Project] > Edit Project**.
@@ -19,4 +38,5 @@ You can find this option under your **[Project] > Edit Project**.
![Housekeeping settings](img/housekeeping_settings.png)
[ce-2371]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2371 "Housekeeping merge request"
-[man]: https://www.kernel.org/pub/software/scm/git/docs/git-gc.html "git gc man page"
+[man-gc]: https://www.kernel.org/pub/software/scm/git/docs/git-gc.html "git gc man page"
+[man-repack]: https://www.kernel.org/pub/software/scm/git/docs/git-repack.html \ No newline at end of file
diff --git a/doc/administration/img/custom_hooks_error_msg.png b/doc/administration/img/custom_hooks_error_msg.png
index 92e87e15fb3..1b3277bef16 100644
--- a/doc/administration/img/custom_hooks_error_msg.png
+++ b/doc/administration/img/custom_hooks_error_msg.png
Binary files differ
diff --git a/doc/administration/img/high_availability/active-active-diagram.png b/doc/administration/img/high_availability/active-active-diagram.png
index 81259e0ae93..4f5984b88fe 100644
--- a/doc/administration/img/high_availability/active-active-diagram.png
+++ b/doc/administration/img/high_availability/active-active-diagram.png
Binary files differ
diff --git a/doc/administration/img/high_availability/active-passive-diagram.png b/doc/administration/img/high_availability/active-passive-diagram.png
index f69ff1d0357..3b42ce5911c 100644
--- a/doc/administration/img/high_availability/active-passive-diagram.png
+++ b/doc/administration/img/high_availability/active-passive-diagram.png
Binary files differ
diff --git a/doc/administration/img/housekeeping_settings.png b/doc/administration/img/housekeeping_settings.png
index 6ebc6205635..acc4506993a 100644
--- a/doc/administration/img/housekeeping_settings.png
+++ b/doc/administration/img/housekeeping_settings.png
Binary files differ
diff --git a/doc/administration/img/integration/plantuml-example.png b/doc/administration/img/integration/plantuml-example.png
new file mode 100644
index 00000000000..cb64eca1a8a
--- /dev/null
+++ b/doc/administration/img/integration/plantuml-example.png
Binary files differ
diff --git a/doc/administration/img/raketasks/check_repos_output.png b/doc/administration/img/raketasks/check_repos_output.png
new file mode 100644
index 00000000000..7fda2ba0c0f
--- /dev/null
+++ b/doc/administration/img/raketasks/check_repos_output.png
Binary files differ
diff --git a/doc/administration/img/repository_storages_admin_ui.png b/doc/administration/img/repository_storages_admin_ui.png
index 599350bc098..3e76c5b282c 100644
--- a/doc/administration/img/repository_storages_admin_ui.png
+++ b/doc/administration/img/repository_storages_admin_ui.png
Binary files differ
diff --git a/doc/administration/integration/koding.md b/doc/administration/integration/koding.md
index a2c358af095..b95c425842c 100644
--- a/doc/administration/integration/koding.md
+++ b/doc/administration/integration/koding.md
@@ -61,6 +61,7 @@ executing commands in the following snippet.
```bash
git clone https://github.com/koding/koding.git
cd koding
+docker-compose -f docker-compose-init.yml run init
docker-compose up
```
diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md
new file mode 100644
index 00000000000..b21817c1fd3
--- /dev/null
+++ b/doc/administration/integration/plantuml.md
@@ -0,0 +1,97 @@
+# PlantUML & GitLab
+
+> [Introduced][ce-8537] in GitLab 8.16.
+
+When [PlantUML](http://plantuml.com) integration is enabled and configured in
+GitLab we are able to create simple diagrams in AsciiDoc and Markdown documents
+created in snippets, wikis, and repos.
+
+## PlantUML Server
+
+Before you can enable PlantUML in GitLab; you need to set up your own PlantUML
+server that will generate the diagrams. Installing and configuring your
+own PlantUML server is easy in Debian/Ubuntu distributions using Tomcat.
+
+First you need to create a `plantuml.war` file from the source code:
+
+```
+sudo apt-get install graphviz openjdk-7-jdk git-core maven
+git clone https://github.com/plantuml/plantuml-server.git
+cd plantuml-server
+mvn package
+```
+
+The above sequence of commands will generate a WAR file that can be deployed
+using Tomcat:
+
+```
+sudo apt-get install tomcat7
+sudo cp target/plantuml.war /var/lib/tomcat7/webapps/plantuml.war
+sudo chown tomcat7:tomcat7 /var/lib/tomcat7/webapps/plantuml.war
+sudo service tomcat7 restart
+```
+
+Once the Tomcat service restarts the PlantUML service will be ready and
+listening for requests on port 8080:
+
+```
+http://localhost:8080/plantuml
+```
+
+you can change these defaults by editing the `/etc/tomcat7/server.xml` file.
+
+
+## GitLab
+
+You need to enable PlantUML integration from Settings under Admin Area. To do
+that, login with an Admin account and do following:
+
+ - in GitLab go to **Admin Area** and then **Settings**
+ - scroll to bottom of the page until PlantUML section
+ - check **Enable PlantUML** checkbox
+ - set the PlantUML instance as **PlantUML URL**
+
+## Creating Diagrams
+
+With PlantUML integration enabled and configured, we can start adding diagrams to
+our AsciiDoc snippets, wikis and repos using delimited blocks:
+
+```
+[plantuml, format="png", id="myDiagram", width="200px"]
+--
+Bob->Alice : hello
+Alice -> Bob : Go Away
+--
+```
+
+And in Markdown using fenced code blocks:
+
+ ```plantuml
+ Bob -> Alice : hello
+ Alice -> Bob : Go Away
+ ```
+
+The above blocks will be converted to an HTML img tag with source pointing to the
+PlantUML instance. If the PlantUML server is correctly configured, this should
+render a nice diagram instead of the block:
+
+![PlantUML Integration](../img/integration/plantuml-example.png)
+
+Inside the block you can add any of the supported diagrams by PlantUML such as
+[Sequence](http://plantuml.com/sequence-diagram), [Use Case](http://plantuml.com/use-case-diagram),
+[Class](http://plantuml.com/class-diagram), [Activity](http://plantuml.com/activity-diagram-legacy),
+[Component](http://plantuml.com/component-diagram), [State](http://plantuml.com/state-diagram),
+and [Object](http://plantuml.com/object-diagram) diagrams. You do not need to use the PlantUML
+diagram delimiters `@startuml`/`@enduml` as these are replaced by the AsciiDoc `plantuml` block.
+
+Some parameters can be added to the AsciiDoc block definition:
+
+ - *format*: Can be either `png` or `svg`. Note that `svg` is not supported by
+ all browsers so use with care. The default is `png`.
+ - *id*: A CSS id added to the diagram HTML tag.
+ - *width*: Width attribute added to the img tag.
+ - *height*: Height attribute added to the img tag.
+
+Markdown does not support any parameters and will always use PNG format.
+
+[ce-8537]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8537 \ No newline at end of file
diff --git a/doc/administration/integration/terminal.md b/doc/administration/integration/terminal.md
new file mode 100644
index 00000000000..91e844c7b42
--- /dev/null
+++ b/doc/administration/integration/terminal.md
@@ -0,0 +1,85 @@
+# Web terminals
+
+> [Introduced][ce-7690] in GitLab 8.15. Only project masters and owners can
+ access web terminals.
+
+With the introduction of the [Kubernetes project service][kubservice], GitLab
+gained the ability to store and use credentials for a Kubernetes cluster. One
+of the things it uses these credentials for is providing access to
+[web terminals](../../ci/environments.html#web-terminals) for environments.
+
+## How it works
+
+A detailed overview of the architecture of web terminals and how they work
+can be found in [this document](https://gitlab.com/gitlab-org/gitlab-workhorse/blob/master/doc/terminal.md).
+In brief:
+
+* GitLab relies on the user to provide their own Kubernetes credentials, and to
+ appropriately label the pods they create when deploying.
+* When a user navigates to the terminal page for an environment, they are served
+ a JavaScript application that opens a WebSocket connection back to GitLab.
+* The WebSocket is handled in [Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse),
+ rather than the Rails application server.
+* Workhorse queries Rails for connection details and user permissions; Rails
+ queries Kubernetes for them in the background, using [Sidekiq](../troubleshooting/sidekiq.md)
+* Workhorse acts as a proxy server between the user's browser and the Kubernetes
+ API, passing WebSocket frames between the two.
+* Workhorse regularly polls Rails, terminating the WebSocket connection if the
+ user no longer has permission to access the terminal, or if the connection
+ details have changed.
+
+## Enabling and disabling terminal support
+
+As web terminals use WebSockets, every HTTP/HTTPS reverse proxy in front of
+Workhorse needs to be configured to pass the `Connection` and `Upgrade` headers
+through to the next one in the chain. If you installed GitLab using Omnibus, or
+from source, starting with GitLab 8.15, this should be done by the default
+configuration, so there's no need for you to do anything.
+
+However, if you run a [load balancer](../high_availability/load_balancer.md) in
+front of GitLab, you may need to make some changes to your configuration. These
+guides document the necessary steps for a selection of popular reverse proxies:
+
+* [Apache](https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html)
+* [NGINX](https://www.nginx.com/blog/websocket-nginx/)
+* [HAProxy](http://blog.haproxy.com/2012/11/07/websockets-load-balancing-with-haproxy/)
+* [Varnish](https://www.varnish-cache.org/docs/4.1/users-guide/vcl-example-websockets.html)
+
+Workhorse won't let WebSocket requests through to non-WebSocket endpoints, so
+it's safe to enable support for these headers globally. If you'd rather had a
+narrower set of rules, you can restrict it to URLs ending with `/terminal.ws`
+(although this may still have a few false positives).
+
+If you installed from source, or have made any configuration changes to your
+Omnibus installation before upgrading to 8.15, you may need to make some
+changes to your configuration. See the [8.14 to 8.15 upgrade](../../update/8.14-to-8.15.md#nginx-configuration)
+document for more details.
+
+If you'd like to disable web terminal support in GitLab, just stop passing
+the `Connection` and `Upgrade` hop-by-hop headers in the *first* HTTP reverse
+proxy in the chain. For most users, this will be the NGINX server bundled with
+Omnibus GitLab, in which case, you need to:
+
+* Find the `nginx['proxy_set_headers']` section of your `gitlab.rb` file
+* Ensure the whole block is uncommented, and then comment out or remove the
+ `Connection` and `Upgrade` lines.
+
+For your own load balancer, just reverse the configuration changes recommended
+by the above guides.
+
+When these headers are not passed through, Workhorse will return a
+`400 Bad Request` response to users attempting to use a web terminal. In turn,
+they will receive a `Connection failed` message.
+
+## Limiting WebSocket connection time
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8413)
+in GitLab 8.17.
+
+Terminal sessions use long-lived connections; by default, these may last
+forever. You can configure a maximum session time in the Admin area of your
+GitLab instance if you find this undesirable from a scalability or security
+point of view.
+
+[ce-7690]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7690
+[kubservice]: ../../user/project/integrations/kubernetes.md
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
new file mode 100644
index 00000000000..3587696225c
--- /dev/null
+++ b/doc/administration/job_artifacts.md
@@ -0,0 +1,162 @@
+# Jobs artifacts administration
+
+>**Notes:**
+>- Introduced in GitLab 8.2 and GitLab Runner 0.7.0.
+>- Starting with GitLab 8.4 and GitLab Runner 1.0, the artifacts archive format
+ changed to `ZIP`.
+>- Starting with GitLab 8.17, builds are renamed to jobs.
+>- This is the administration documentation. For the user guide see
+ [pipelines/job_artifacts](../user/project/pipelines/job_artifacts.md).
+
+Artifacts is a list of files and directories which are attached to a job
+after it completes successfully. This feature is enabled by default in all
+GitLab installations. Keep reading if you want to know how to disable it.
+
+## Disabling job artifacts
+
+To disable artifacts site-wide, follow the steps below.
+
+---
+
+**In Omnibus installations:**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
+
+ ```ruby
+ gitlab_rails['artifacts_enabled'] = false
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+---
+
+**In installations from source:**
+
+1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines:
+
+ ```yaml
+ artifacts:
+ enabled: false
+ ```
+
+1. Save the file and [restart GitLab][] for the changes to take effect.
+
+## Storing job artifacts
+
+After a successful job, GitLab Runner uploads an archive containing the job
+artifacts to GitLab.
+
+### Using local storage
+
+To change the location where the artifacts are stored locally, follow the steps
+below.
+
+---
+
+**In Omnibus installations:**
+
+_The artifacts are stored by default in
+`/var/opt/gitlab/gitlab-rails/shared/artifacts`._
+
+1. To change the storage path for example to `/mnt/storage/artifacts`, edit
+ `/etc/gitlab/gitlab.rb` and add the following line:
+
+ ```ruby
+ gitlab_rails['artifacts_path'] = "/mnt/storage/artifacts"
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+---
+
+**In installations from source:**
+
+_The artifacts are stored by default in
+`/home/git/gitlab/shared/artifacts`._
+
+1. To change the storage path for example to `/mnt/storage/artifacts`, edit
+ `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines:
+
+ ```yaml
+ artifacts:
+ enabled: true
+ path: /mnt/storage/artifacts
+ ```
+
+1. Save the file and [restart GitLab][] for the changes to take effect.
+
+### Using object storage
+
+In [GitLab Enterprise Edition Premium][eep] you can use an object storage like
+AWS S3 to store the artifacts.
+
+[Learn how to use the object storage option.][ee-os]
+
+## Expiring artifacts
+
+If an expiry date is used for the artifacts, they are marked for deletion
+right after that date passes. Artifacts are cleaned up by the
+`expire_build_artifacts_worker` cron job which is run by Sidekiq every hour at
+50 minutes (`50 * * * *`).
+
+To change the default schedule on which the artifacts are expired, follow the
+steps below.
+
+---
+
+**In Omnibus installations:**
+
+1. Edit `/etc/gitlab/gitlab.rb` and comment out or add the following line
+
+ ```ruby
+ gitlab_rails['expire_build_artifacts_worker_cron'] = "50 * * * *"
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+---
+
+**In installations from source:**
+
+1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following
+ lines:
+
+ ```yaml
+ expire_build_artifacts_worker:
+ cron: "50 * * * *"
+ ```
+
+1. Save the file and [restart GitLab][] for the changes to take effect.
+
+## Set the maximum file size of the artifacts
+
+Provided the artifacts are enabled, you can change the maximum file size of the
+artifacts through the [Admin area settings](../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size).
+
+## Storage statistics
+
+You can see the total storage used for job artifacts on groups and projects
+in the administration area, as well as through the [groups](../api/groups.md)
+and [projects APIs](../api/projects.md).
+
+## Implementation details
+
+When GitLab receives an artifacts archive, an archive metadata file is also
+generated. This metadata file describes all the entries that are located in the
+artifacts archive itself. The metadata file is in a binary format, with
+additional GZIP compression.
+
+GitLab does not extract the artifacts archive in order to save space, memory
+and disk I/O. It instead inspects the metadata file which contains all the
+relevant information. This is especially important when there is a lot of
+artifacts, or an archive is a very large file.
+
+When clicking on a specific file, [GitLab Workhorse] extracts it
+from the archive and the download begins. This implementation saves space,
+memory and disk I/O.
+
+[reconfigure gitlab]: restart_gitlab.md "How to restart GitLab"
+[restart gitlab]: restart_gitlab.md "How to restart GitLab"
+[gitlab workhorse]: https://gitlab.com/gitlab-org/gitlab-workhorse "GitLab Workhorse repository"
+[ee-os]: https://docs.gitlab.com/ee/administration/job_artifacts.html#using-object-storage
+[eep]: https://about.gitlab.com/gitlab-ee/ "GitLab Enterprise Edition Premium"
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 737b39db16c..4b8d5c5cc87 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -1,4 +1,4 @@
-## Log system
+# Log system
GitLab has an advanced log system where everything is logged so that you
can analyze your instance using various system log files. In addition to
@@ -9,11 +9,12 @@ documentation](http://docs.gitlab.com/ee/administration/audit_events.html)
System log files are typically plain text in a standard log file format.
This guide talks about how to read and use these system log files.
-### production.log
+## `production.log`
This file lives in `/var/log/gitlab/gitlab-rails/production.log` for
-omnibus package or in `/home/git/gitlab/log/production.log` for
-installations from source.
+Omnibus GitLab packages or in `/home/git/gitlab/log/production.log` for
+installations from source. (When Gitlab is running in an environment
+other than production, the corresponding logfile is shown here.)
It contains information about all performed requests. You can see the
URL and type of request, IP address and what exactly parts of code were
@@ -45,10 +46,10 @@ In this example we can see that server processed an HTTP request with URL
19:34:53 +0200. Also we can see that request was processed by
`Projects::TreeController`.
-### application.log
+## `application.log`
This file lives in `/var/log/gitlab/gitlab-rails/application.log` for
-omnibus package or in `/home/git/gitlab/log/application.log` for
+Omnibus GitLab packages or in `/home/git/gitlab/log/application.log` for
installations from source.
It helps you discover events happening in your instance such as user creation,
@@ -62,10 +63,10 @@ October 07, 2014 11:25: User "Claudie Hodkiewicz" (nasir_stehr@olson.co.uk) was
October 07, 2014 11:25: Project "project133" was removed
```
-### githost.log
+## `githost.log`
This file lives in `/var/log/gitlab/gitlab-rails/githost.log` for
-omnibus package or in `/home/git/gitlab/log/githost.log` for
+Omnibus GitLab packages or in `/home/git/gitlab/log/githost.log` for
installations from source.
GitLab has to interact with Git repositories but in some rare cases
@@ -80,10 +81,10 @@ December 03, 2014 13:20 -> ERROR -> Command failed [1]: /usr/bin/git --git-dir=/
error: failed to push some refs to '/Users/vsizov/gitlab-development-kit/repositories/gitlabhq/gitlab_git.git'
```
-### sidekiq.log
+## `sidekiq.log`
This file lives in `/var/log/gitlab/gitlab-rails/sidekiq.log` for
-omnibus package or in `/home/git/gitlab/log/sidekiq.log` for
+Omnibus GitLab packages or in `/home/git/gitlab/log/sidekiq.log` for
installations from source.
GitLab uses background jobs for processing tasks which can take a long
@@ -95,10 +96,10 @@ this file. For example:
2014-06-10T18:18:26Z 14299 TID-55uqo INFO: Booting Sidekiq 3.0.0 with redis options {:url=>"redis://localhost:6379/0", :namespace=>"sidekiq"}
```
-### gitlab-shell.log
+## `gitlab-shell.log`
This file lives in `/var/log/gitlab/gitlab-shell/gitlab-shell.log` for
-omnibus package or in `/home/git/gitlab-shell/gitlab-shell.log` for
+Omnibus GitLab packages or in `/home/git/gitlab-shell/gitlab-shell.log` for
installations from source.
GitLab shell is used by Gitlab for executing Git commands and provide
@@ -109,10 +110,10 @@ I, [2015-02-13T06:17:00.671315 #9291] INFO -- : Adding project root/example.git
I, [2015-02-13T06:17:00.679433 #9291] INFO -- : Moving existing hooks directory and symlinking global hooks directory for /var/opt/gitlab/git-data/repositories/root/example.git.
```
-### unicorn\_stderr.log
+## `unicorn\_stderr.log`
This file lives in `/var/log/gitlab/unicorn/unicorn_stderr.log` for
-omnibus package or in `/home/git/gitlab/log/unicorn_stderr.log` for
+Omnibus GitLab packages or in `/home/git/gitlab/log/unicorn_stderr.log` for
installations from source.
Unicorn is a high-performance forking Web server which is used for
@@ -135,3 +136,13 @@ I, [2015-02-13T07:16:01.530733 #9047] INFO -- : reaped #<Process::Status: pid 9
I, [2015-02-13T07:16:01.534501 #13379] INFO -- : worker=1 spawned pid=13379
I, [2015-02-13T07:16:01.534848 #13379] INFO -- : worker=1 ready
```
+
+## `repocheck.log`
+
+This file lives in `/var/log/gitlab/gitlab-rails/repocheck.log` for
+Omnibus GitLab packages or in `/home/git/gitlab/log/repocheck.log` for
+installations from source.
+
+It logs information whenever a [repository check is run][repocheck] on a project.
+
+[repocheck]: repository_checks.md
diff --git a/doc/administration/monitoring/performance/gitlab_configuration.md b/doc/administration/monitoring/performance/gitlab_configuration.md
new file mode 100644
index 00000000000..771584268d9
--- /dev/null
+++ b/doc/administration/monitoring/performance/gitlab_configuration.md
@@ -0,0 +1,40 @@
+# GitLab Configuration
+
+GitLab Performance Monitoring is disabled by default. To enable it and change any of its
+settings, navigate to the Admin area in **Settings > Metrics**
+(`/admin/application_settings`).
+
+The minimum required settings you need to set are the InfluxDB host and port.
+Make sure _Enable InfluxDB Metrics_ is checked and hit **Save** to save the
+changes.
+
+---
+
+![GitLab Performance Monitoring Admin Settings](img/metrics_gitlab_configuration_settings.png)
+
+---
+
+Finally, a restart of all GitLab processes is required for the changes to take
+effect:
+
+```bash
+# For Omnibus installations
+sudo gitlab-ctl restart
+
+# For installations from source
+sudo service gitlab restart
+```
+
+## Pending Migrations
+
+When any migrations are pending, the metrics are disabled until the migrations
+have been performed.
+
+---
+
+Read more on:
+
+- [Introduction to GitLab Performance Monitoring](introduction.md)
+- [InfluxDB Configuration](influxdb_configuration.md)
+- [InfluxDB Schema](influxdb_schema.md)
+- [Grafana Install/Configuration](grafana_configuration.md)
diff --git a/doc/administration/monitoring/performance/grafana_configuration.md b/doc/administration/monitoring/performance/grafana_configuration.md
new file mode 100644
index 00000000000..7947b0fedc4
--- /dev/null
+++ b/doc/administration/monitoring/performance/grafana_configuration.md
@@ -0,0 +1,111 @@
+# Grafana Configuration
+
+[Grafana](http://grafana.org/) is a tool that allows you to visualize time
+series metrics through graphs and dashboards. It supports several backend
+data stores, including InfluxDB. GitLab writes performance data to InfluxDB
+and Grafana will allow you to query InfluxDB to display useful graphs.
+
+For the easiest installation and configuration, install Grafana on the same
+server as InfluxDB. For larger installations, you may want to split out these
+services.
+
+## Installation
+
+Grafana supplies package repositories (Yum/Apt) for easy installation.
+See [Grafana installation documentation](http://docs.grafana.org/installation/)
+for detailed steps.
+
+> **Note**: Before starting Grafana for the first time, set the admin user
+and password in `/etc/grafana/grafana.ini`. Otherwise, the default password
+will be `admin`.
+
+## Configuration
+
+Login as the admin user. Expand the menu by clicking the Grafana logo in the
+top left corner. Choose 'Data Sources' from the menu. Then, click 'Add new'
+in the top bar.
+
+![Grafana empty data source page](img/grafana_data_source_empty.png)
+
+Fill in the configuration details for the InfluxDB data source. Save and
+Test Connection to ensure the configuration is correct.
+
+- **Name**: InfluxDB
+- **Default**: Checked
+- **Type**: InfluxDB 0.9.x (Even if you're using InfluxDB 0.10.x)
+- **Url**: https://localhost:8086 (Or the remote URL if you've installed InfluxDB
+on a separate server)
+- **Access**: proxy
+- **Database**: gitlab
+- **User**: admin (Or the username configured when setting up InfluxDB)
+- **Password**: The password configured when you set up InfluxDB
+
+![Grafana data source configurations](img/grafana_data_source_configuration.png)
+
+## Apply retention policies and create continuous queries
+
+If you intend to import the GitLab provided Grafana dashboards, you will need to
+set up the right retention policies and continuous queries. The easiest way of
+doing this is by using the [influxdb-management](https://gitlab.com/gitlab-org/influxdb-management)
+repository.
+
+To use this repository you must first clone it:
+
+```
+git clone https://gitlab.com/gitlab-org/influxdb-management.git
+cd influxdb-management
+```
+
+Next you must install the required dependencies:
+
+```
+gem install bundler
+bundle install
+```
+
+Now you must configure the repository by first copying `.env.example` to `.env`
+and then editing the `.env` file to contain the correct InfluxDB settings. Once
+configured you can simply run `bundle exec rake` and the InfluxDB database will
+be configured for you.
+
+For more information see the [influxdb-management README](https://gitlab.com/gitlab-org/influxdb-management/blob/master/README.md).
+
+## Import Dashboards
+
+You can now import a set of default dashboards that will give you a good
+start on displaying useful information. GitLab has published a set of default
+[Grafana dashboards][grafana-dashboards] to get you started. Clone the
+repository or download a zip/tarball, then follow these steps to import each
+JSON file.
+
+Open the dashboard dropdown menu and click 'Import'
+
+![Grafana dashboard dropdown](img/grafana_dashboard_dropdown.png)
+
+Click 'Choose file' and browse to the location where you downloaded or cloned
+the dashboard repository. Pick one of the JSON files to import.
+
+![Grafana dashboard import](img/grafana_dashboard_import.png)
+
+Once the dashboard is imported, be sure to click save icon in the top bar. If
+you do not save the dashboard after importing it will be removed when you
+navigate away.
+
+![Grafana save icon](img/grafana_save_icon.png)
+
+Repeat this process for each dashboard you wish to import.
+
+Alternatively you can automatically import all the dashboards into your Grafana
+instance. See the README of the [Grafana dashboards][grafana-dashboards]
+repository for more information on this process.
+
+[grafana-dashboards]: https://gitlab.com/gitlab-org/grafana-dashboards
+
+---
+
+Read more on:
+
+- [Introduction to GitLab Performance Monitoring](introduction.md)
+- [GitLab Configuration](gitlab_configuration.md)
+- [InfluxDB Installation/Configuration](influxdb_configuration.md)
+- [InfluxDB Schema](influxdb_schema.md)
diff --git a/doc/administration/monitoring/performance/img/grafana_dashboard_dropdown.png b/doc/administration/monitoring/performance/img/grafana_dashboard_dropdown.png
new file mode 100644
index 00000000000..51eef90068d
--- /dev/null
+++ b/doc/administration/monitoring/performance/img/grafana_dashboard_dropdown.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/grafana_dashboard_import.png b/doc/administration/monitoring/performance/img/grafana_dashboard_import.png
new file mode 100644
index 00000000000..7761ea00522
--- /dev/null
+++ b/doc/administration/monitoring/performance/img/grafana_dashboard_import.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/grafana_data_source_configuration.png b/doc/administration/monitoring/performance/img/grafana_data_source_configuration.png
new file mode 100644
index 00000000000..3e749eb8f9d
--- /dev/null
+++ b/doc/administration/monitoring/performance/img/grafana_data_source_configuration.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/grafana_data_source_empty.png b/doc/administration/monitoring/performance/img/grafana_data_source_empty.png
new file mode 100644
index 00000000000..33fcaaaef64
--- /dev/null
+++ b/doc/administration/monitoring/performance/img/grafana_data_source_empty.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/grafana_save_icon.png b/doc/administration/monitoring/performance/img/grafana_save_icon.png
new file mode 100644
index 00000000000..c18f2147e9d
--- /dev/null
+++ b/doc/administration/monitoring/performance/img/grafana_save_icon.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/metrics_gitlab_configuration_settings.png b/doc/administration/monitoring/performance/img/metrics_gitlab_configuration_settings.png
new file mode 100644
index 00000000000..13bfd097b81
--- /dev/null
+++ b/doc/administration/monitoring/performance/img/metrics_gitlab_configuration_settings.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/request_profile_result.png b/doc/administration/monitoring/performance/img/request_profile_result.png
new file mode 100644
index 00000000000..8ebd74c2d3c
--- /dev/null
+++ b/doc/administration/monitoring/performance/img/request_profile_result.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/request_profiling_token.png b/doc/administration/monitoring/performance/img/request_profiling_token.png
new file mode 100644
index 00000000000..9160407e028
--- /dev/null
+++ b/doc/administration/monitoring/performance/img/request_profiling_token.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/influxdb_configuration.md b/doc/administration/monitoring/performance/influxdb_configuration.md
new file mode 100644
index 00000000000..c30cd2950d8
--- /dev/null
+++ b/doc/administration/monitoring/performance/influxdb_configuration.md
@@ -0,0 +1,193 @@
+# InfluxDB Configuration
+
+The default settings provided by [InfluxDB] are not sufficient for a high traffic
+GitLab environment. The settings discussed in this document are based on the
+settings GitLab uses for GitLab.com, depending on your own needs you may need to
+further adjust them.
+
+If you are intending to run InfluxDB on the same server as GitLab, make sure
+you have plenty of RAM since InfluxDB can use quite a bit depending on traffic.
+
+Unless you are going with a budget setup, it's advised to run it separately.
+
+## Requirements
+
+- InfluxDB 0.9.5 or newer
+- A fairly modern version of Linux
+- At least 4GB of RAM
+- At least 10GB of storage for InfluxDB data
+
+Note that the RAM and storage requirements can differ greatly depending on the
+amount of data received/stored. To limit the amount of stored data users can
+look into [InfluxDB Retention Policies][influxdb-retention].
+
+## Installation
+
+Installing InfluxDB is out of the scope of this document. Please refer to the
+[InfluxDB documentation].
+
+## InfluxDB Server Settings
+
+Since InfluxDB has many settings that users may wish to customize themselves
+(e.g. what port to run InfluxDB on), we'll only cover the essentials.
+
+The configuration file in question is usually located at
+`/etc/influxdb/influxdb.conf`. Whenever you make a change in this file,
+InfluxDB needs to be restarted.
+
+### Storage Engine
+
+InfluxDB comes with different storage engines and as of InfluxDB 0.9.5 a new
+storage engine is available, called [TSM Tree]. All users **must** use the new
+`tsm1` storage engine as this [will be the default engine][tsm1-commit] in
+upcoming InfluxDB releases.
+
+Make sure you have the following in your configuration file:
+
+```
+[data]
+ dir = "/var/lib/influxdb/data"
+ engine = "tsm1"
+```
+
+### Admin Panel
+
+Production environments should have the InfluxDB admin panel **disabled**. This
+feature can be disabled by adding the following to your InfluxDB configuration
+file:
+
+```
+[admin]
+ enabled = false
+```
+
+### HTTP
+
+HTTP is required when using the [InfluxDB CLI] or other tools such as Grafana,
+thus it should be enabled. When enabling make sure to _also_ enable
+authentication:
+
+```
+[http]
+ enabled = true
+ auth-enabled = true
+```
+
+_**Note:** Before you enable authentication, you might want to [create an
+admin user](#create-a-new-admin-user)._
+
+### UDP
+
+GitLab writes data to InfluxDB via UDP and thus this must be enabled. Enabling
+UDP can be done using the following settings:
+
+```
+[[udp]]
+ enabled = true
+ bind-address = ":8089"
+ database = "gitlab"
+ batch-size = 1000
+ batch-pending = 5
+ batch-timeout = "1s"
+ read-buffer = 209715200
+```
+
+This does the following:
+
+1. Enable UDP and bind it to port 8089 for all addresses.
+2. Store any data received in the "gitlab" database.
+3. Define a batch of points to be 1000 points in size and allow a maximum of
+ 5 batches _or_ flush them automatically after 1 second.
+4. Define a UDP read buffer size of 200 MB.
+
+One of the most important settings here is the UDP read buffer size as if this
+value is set too low, packets will be dropped. You must also make sure the OS
+buffer size is set to the same value, the default value is almost never enough.
+
+To set the OS buffer size to 200 MB, on Linux you can run the following command:
+
+```bash
+sysctl -w net.core.rmem_max=209715200
+```
+
+To make this permanent, add the following to `/etc/sysctl.conf` and restart the
+server:
+
+```bash
+net.core.rmem_max=209715200
+```
+
+It is **very important** to make sure the buffer sizes are large enough to
+handle all data sent to InfluxDB as otherwise you _will_ lose data. The above
+buffer sizes are based on the traffic for GitLab.com. Depending on the amount of
+traffic, users may be able to use a smaller buffer size, but we highly recommend
+using _at least_ 100 MB.
+
+When enabling UDP, users should take care to not expose the port to the public,
+as doing so will allow anybody to write data into your InfluxDB database (as
+[InfluxDB's UDP protocol][udp] doesn't support authentication). We recommend either
+whitelisting the allowed IP addresses/ranges, or setting up a VLAN and only
+allowing traffic from members of said VLAN.
+
+## Create a new admin user
+
+If you want to [enable authentication](#http), you might want to [create an
+admin user][influx-admin]:
+
+```
+influx -execute "CREATE USER jeff WITH PASSWORD '1234' WITH ALL PRIVILEGES"
+```
+
+## Create the `gitlab` database
+
+Once you get InfluxDB up and running, you need to create a database for GitLab.
+Make sure you have changed the [storage engine](#storage-engine) to `tsm1`
+before creating a database.
+
+_**Note:** If you [created an admin user](#create-a-new-admin-user) and enabled
+[HTTP authentication](#http), remember to append the username (`-username <username>`)
+and password (`-password <password>`) you set earlier to the commands below._
+
+Run the following command to create a database named `gitlab`:
+
+```bash
+influx -execute 'CREATE DATABASE gitlab'
+```
+
+The name **must** be `gitlab`, do not use any other name.
+
+Next, make sure that the database was successfully created:
+
+```bash
+influx -execute 'SHOW DATABASES'
+```
+
+The output should be similar to:
+
+```
+name: databases
+---------------
+name
+_internal
+gitlab
+```
+
+That's it! Now your GitLab instance should send data to InfluxDB.
+
+---
+
+Read more on:
+
+- [Introduction to GitLab Performance Monitoring](introduction.md)
+- [GitLab Configuration](gitlab_configuration.md)
+- [InfluxDB Schema](influxdb_schema.md)
+- [Grafana Install/Configuration](grafana_configuration.md)
+
+[influxdb-retention]: https://docs.influxdata.com/influxdb/v0.9/query_language/database_management/#retention-policy-management
+[influxdb documentation]: https://docs.influxdata.com/influxdb/v0.9/
+[influxdb cli]: https://docs.influxdata.com/influxdb/v0.9/tools/shell/
+[udp]: https://docs.influxdata.com/influxdb/v0.9/write_protocols/udp/
+[influxdb]: https://influxdata.com/time-series-platform/influxdb/
+[tsm tree]: https://influxdata.com/blog/new-storage-engine-time-structured-merge-tree/
+[tsm1-commit]: https://github.com/influxdata/influxdb/commit/15d723dc77651bac83e09e2b1c94be480966cb0d
+[influx-admin]: https://docs.influxdata.com/influxdb/v0.9/administration/authentication_and_authorization/#create-a-new-admin-user
diff --git a/doc/administration/monitoring/performance/influxdb_schema.md b/doc/administration/monitoring/performance/influxdb_schema.md
new file mode 100644
index 00000000000..eff0e29f58d
--- /dev/null
+++ b/doc/administration/monitoring/performance/influxdb_schema.md
@@ -0,0 +1,97 @@
+# InfluxDB Schema
+
+The following measurements are currently stored in InfluxDB:
+
+- `PROCESS_file_descriptors`
+- `PROCESS_gc_statistics`
+- `PROCESS_memory_usage`
+- `PROCESS_method_calls`
+- `PROCESS_object_counts`
+- `PROCESS_transactions`
+- `PROCESS_views`
+- `events`
+
+Here, `PROCESS` is replaced with either `rails` or `sidekiq` depending on the
+process type. In all series, any form of duration is stored in milliseconds.
+
+## PROCESS_file_descriptors
+
+This measurement contains the number of open file descriptors over time. The
+value field `value` contains the number of descriptors.
+
+## PROCESS_gc_statistics
+
+This measurement contains Ruby garbage collection statistics such as the amount
+of minor/major GC runs (relative to the last sampling interval), the time spent
+in garbage collection cycles, and all fields/values returned by `GC.stat`.
+
+## PROCESS_memory_usage
+
+This measurement contains the process' memory usage (in bytes) over time. The
+value field `value` contains the number of bytes.
+
+## PROCESS_method_calls
+
+This measurement contains the methods called during a transaction along with
+their duration, and a name of the transaction action that invoked the method (if
+available). The method call duration is stored in the value field `duration`,
+while the method name is stored in the tag `method`. The tag `action` contains
+the full name of the transaction action. Both the `method` and `action` fields
+are in the following format:
+
+```
+ClassName#method_name
+```
+
+For example, a method called by the `show` method in the `UsersController` class
+would have `action` set to `UsersController#show`.
+
+## PROCESS_object_counts
+
+This measurement is used to store retained Ruby objects (per class) and the
+amount of retained objects. The number of objects is stored in the `count` value
+field while the class name is stored in the `type` tag.
+
+## PROCESS_transactions
+
+This measurement is used to store basic transaction details such as the time it
+took to complete a transaction, how much time was spent in SQL queries, etc. The
+following value fields are available:
+
+| Value | Description |
+| ----- | ----------- |
+| `duration` | The total duration of the transaction |
+| `allocated_memory` | The amount of bytes allocated while the transaction was running. This value is only reliable when using single-threaded application servers |
+| `method_duration` | The total time spent in method calls |
+| `sql_duration` | The total time spent in SQL queries |
+| `view_duration` | The total time spent in views |
+
+## PROCESS_views
+
+This measurement is used to store view rendering timings for a transaction. The
+following value fields are available:
+
+| Value | Description |
+| ----- | ----------- |
+| `duration` | The rendering time of the view |
+| `view` | The path of the view, relative to the application's root directory |
+
+The `action` tag contains the action name of the transaction that rendered the
+view.
+
+## events
+
+This measurement is used to store generic events such as the number of Git
+pushes, Emails sent, etc. Each point in this measurement has a single value
+field called `count`. The value of this field is simply set to `1`. Each point
+also has at least one tag: `event`. This tag's value is set to the event name.
+Depending on the event type additional tags may be available as well.
+
+---
+
+Read more on:
+
+- [Introduction to GitLab Performance Monitoring](introduction.md)
+- [GitLab Configuration](gitlab_configuration.md)
+- [InfluxDB Configuration](influxdb_configuration.md)
+- [Grafana Install/Configuration](grafana_configuration.md)
diff --git a/doc/administration/monitoring/performance/introduction.md b/doc/administration/monitoring/performance/introduction.md
new file mode 100644
index 00000000000..17c2b4b70d3
--- /dev/null
+++ b/doc/administration/monitoring/performance/introduction.md
@@ -0,0 +1,70 @@
+# GitLab Performance Monitoring
+
+GitLab comes with its own application performance measuring system as of GitLab
+8.4, simply called "GitLab Performance Monitoring". GitLab Performance Monitoring is available in both the
+Community and Enterprise editions.
+
+Apart from this introduction, you are advised to read through the following
+documents in order to understand and properly configure GitLab Performance Monitoring:
+
+- [GitLab Configuration](gitlab_configuration.md)
+- [InfluxDB Install/Configuration](influxdb_configuration.md)
+- [InfluxDB Schema](influxdb_schema.md)
+- [Grafana Install/Configuration](grafana_configuration.md)
+
+>**Note:**
+Omnibus GitLab 8.16 includes Prometheus as an additional tool to collect
+metrics. It will eventually replace InfluxDB when their metrics collection is
+on par. Read more in the [Prometheus documentation](../prometheus/index.md).
+
+## Introduction to GitLab Performance Monitoring
+
+GitLab Performance Monitoring makes it possible to measure a wide variety of statistics
+including (but not limited to):
+
+- The time it took to complete a transaction (a web request or Sidekiq job).
+- The time spent in running SQL queries and rendering HAML views.
+- The time spent executing (instrumented) Ruby methods.
+- Ruby object allocations, and retained objects in particular.
+- System statistics such as the process' memory usage and open file descriptors.
+- Ruby garbage collection statistics.
+
+Metrics data is written to [InfluxDB][influxdb] over [UDP][influxdb-udp]. Stored
+data can be visualized using [Grafana][grafana] or any other application that
+supports reading data from InfluxDB. Alternatively data can be queried using the
+InfluxDB CLI.
+
+## Metric Types
+
+Two types of metrics are collected:
+
+1. Transaction specific metrics.
+1. Sampled metrics, collected at a certain interval in a separate thread.
+
+### Transaction Metrics
+
+Transaction metrics are metrics that can be associated with a single
+transaction. This includes statistics such as the transaction duration, timings
+of any executed SQL queries, time spent rendering HAML views, etc. These metrics
+are collected for every Rack request and Sidekiq job processed.
+
+### Sampled Metrics
+
+Sampled metrics are metrics that can't be associated with a single transaction.
+Examples include garbage collection statistics and retained Ruby objects. These
+metrics are collected at a regular interval. This interval is made up out of two
+parts:
+
+1. A user defined interval.
+1. A randomly generated offset added on top of the interval, the same offset
+ can't be used twice in a row.
+
+The actual interval can be anywhere between a half of the defined interval and a
+half above the interval. For example, for a user defined interval of 15 seconds
+the actual interval can be anywhere between 7.5 and 22.5. The interval is
+re-generated for every sampling run instead of being generated once and re-used
+for the duration of the process' lifetime.
+
+[influxdb]: https://influxdata.com/time-series-platform/influxdb/
+[influxdb-udp]: https://docs.influxdata.com/influxdb/v0.9/write_protocols/udp/
+[grafana]: http://grafana.org/
diff --git a/doc/administration/monitoring/performance/prometheus.md b/doc/administration/monitoring/performance/prometheus.md
new file mode 100644
index 00000000000..d73ef5d1789
--- /dev/null
+++ b/doc/administration/monitoring/performance/prometheus.md
@@ -0,0 +1 @@
+This document was moved to [monitoring/prometheus](../prometheus/index.md).
diff --git a/doc/administration/monitoring/performance/request_profiling.md b/doc/administration/monitoring/performance/request_profiling.md
new file mode 100644
index 00000000000..c358dfbead2
--- /dev/null
+++ b/doc/administration/monitoring/performance/request_profiling.md
@@ -0,0 +1,16 @@
+# Request Profiling
+
+## Procedure
+1. Grab the profiling token from `Monitoring > Requests Profiles` admin page
+(highlighted in a blue in the image below).
+![Profile token](img/request_profiling_token.png)
+1. Pass the header `X-Profile-Token: <token>` to the request you want to profile. You can use any of these tools
+ * [ModHeader](https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj) Chrome extension
+ * [Modify Headers](https://addons.mozilla.org/en-US/firefox/addon/modify-headers/) Firefox extension
+ * `curl --header 'X-Profile-Token: <token>' https://gitlab.example.com/group/project`
+1. Once request is finished (which will take a little longer than usual), you can
+view the profiling output from `Monitoring > Requests Profiles` admin page.
+![Profiling output](img/request_profile_result.png)
+
+## Cleaning up
+Profiling output will be cleared out every day via a Sidekiq worker.
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
new file mode 100644
index 00000000000..07c05b5a6fb
--- /dev/null
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -0,0 +1,47 @@
+# GitLab Prometheus metrics
+
+>**Note:**
+Available since [Omnibus GitLab 9.3][29118]. Currently experimental. For installations from source
+you'll have to configure it yourself.
+
+GitLab monitors its own internal service metrics, and makes them available at the `/-/metrics` endpoint. Unlike other [Prometheus] exporters, this endpoint requires authentication as it is available on the same URL and port as user traffic.
+
+To enable the GitLab Prometheus metrics:
+
+1. Log into GitLab as an administrator, and go to the Admin area.
+1. Click on the gear, then click on Settings.
+1. Find the `Metrics - Prometheus` section, and click `Enable Prometheus Metrics`
+1. [Restart GitLab][restart] for the changes to take effect
+
+## Collecting the metrics
+
+Since the metrics endpoint is available on the same host and port as other traffic, it requires authentication. The token and URL to access is displayed on the [Health Check][health-check] page.
+
+Currently the embedded Prometheus server is not automatically configured to collect metrics from this endpoint. We recommend setting up another Prometheus server, because the embedded server configuration is overwritten one every reconfigure of GitLab. In the future this will not be required.
+
+## Metrics available
+
+In this experimental phase, only a few metrics are available:
+
+| Metric | Type | Description |
+| ------ | ---- | ----------- |
+| db_ping_timeout | Gauge | Whether or not the last database ping timed out |
+| db_ping_success | Gauge | Whether or not the last database ping succeeded |
+| db_ping_latency | Gauge | Round trip time of the database ping |
+| redis_ping_timeout | Gauge | Whether or not the last redis ping timed out |
+| redis_ping_success | Gauge | Whether or not the last redis ping succeeded |
+| redis_ping_latency | Gauge | Round trip time of the redis ping |
+| filesystem_access_latency | gauge | Latency in accessing a specific filesystem |
+| filesystem_accessible | gauge | Whether or not a specific filesystem is accessible |
+| filesystem_write_latency | gauge | Write latency of a specific filesystem |
+| filesystem_writable | gauge | Whether or not the filesystem is writable |
+| filesystem_read_latency | gauge | Read latency of a specific filesystem |
+| filesystem_readable | gauge | Whether or not the filesystem is readable |
+| user_sessions_logins | Counter | Counter of how many users have logged in |
+
+[← Back to the main Prometheus page](index.md)
+
+[29118]: https://gitlab.com/gitlab-org/gitlab-ce/issues/29118
+[Prometheus]: https://prometheus.io
+[restart]: ../../restart_gitlab.md#omnibus-gitlab-restart
+[health-check]: ../../../user/admin_area/monitoring/health_check.md
diff --git a/doc/administration/monitoring/prometheus/gitlab_monitor_exporter.md b/doc/administration/monitoring/prometheus/gitlab_monitor_exporter.md
new file mode 100644
index 00000000000..f68b03d1ade
--- /dev/null
+++ b/doc/administration/monitoring/prometheus/gitlab_monitor_exporter.md
@@ -0,0 +1,30 @@
+# GitLab monitor exporter
+
+>**Note:**
+Available since [Omnibus GitLab 8.17][1132]. For installations from source
+you'll have to install and configure it yourself.
+
+The [GitLab monitor exporter] allows you to measure various GitLab metrics, pulled from Redis and the database.
+
+To enable the GitLab monitor exporter:
+
+1. [Enable Prometheus](index.md#configuring-prometheus)
+1. Edit `/etc/gitlab/gitlab.rb`
+1. Add or find and uncomment the following line, making sure it's set to `true`:
+
+ ```ruby
+ gitlab_monitor['enable'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
+ take effect
+
+Prometheus will now automatically begin collecting performance data from
+the GitLab monitor exporter exposed under `localhost:9168`.
+
+[← Back to the main Prometheus page](index.md)
+
+[1132]: https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/1132
+[GitLab monitor exporter]: https://gitlab.com/gitlab-org/gitlab-monitor
+[prometheus]: https://prometheus.io
+[reconfigure]: ../../restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md
new file mode 100644
index 00000000000..695fdf09a87
--- /dev/null
+++ b/doc/administration/monitoring/prometheus/index.md
@@ -0,0 +1,170 @@
+# GitLab Prometheus
+
+>**Notes:**
+- Prometheus and the various exporters listed in this page are bundled in the
+ Omnibus GitLab package. Check each exporter's documentation for the timeline
+ they got added. For installations from source you will have to install them
+ yourself. Over subsequent releases additional GitLab metrics will be captured.
+- Prometheus services are on by default with GitLab 9.0.
+- Prometheus and its exporters do not authenticate users, and will be available
+ to anyone who can access them.
+
+[Prometheus] is a powerful time-series monitoring service, providing a flexible
+platform for monitoring GitLab and other software products.
+GitLab provides out of the box monitoring with Prometheus, providing easy
+access to high quality time-series monitoring of GitLab services.
+
+## Overview
+
+Prometheus works by periodically connecting to data sources and collecting their
+performance metrics via the [various exporters](#prometheus-exporters). To view
+and work with the monitoring data, you can either
+[connect directly to Prometheus](#viewing-performance-metrics) or utilize a
+dashboard tool like [Grafana].
+
+## Configuring Prometheus
+
+>**Note:**
+For installations from source you'll have to install and configure it yourself.
+
+Prometheus and it's exporters are on by default, starting with GitLab 9.0.
+Prometheus will run as the `gitlab-prometheus` user and listen on
+`http://localhost:9090`. Each exporter will be automatically be set up as a
+monitoring target for Prometheus, unless individually disabled.
+
+To disable Prometheus and all of its exporters, as well as any added in the future:
+
+1. Edit `/etc/gitlab/gitlab.rb`
+1. Add or find and uncomment the following line, making sure it's set to `false`:
+
+ ```ruby
+ prometheus_monitoring['enable'] = false
+ ```
+
+1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
+ take effect
+
+## Changing the port Prometheus listens on
+
+>**Note:**
+The following change was added in [GitLab Omnibus 8.17][1261]. Although possible,
+it's not recommended to change the default address and port Prometheus listens
+on as this might affect or conflict with other services running on the GitLab
+server. Proceed at your own risk.
+
+To change the address/port that Prometheus listens on:
+
+1. Edit `/etc/gitlab/gitlab.rb`
+1. Add or find and uncomment the following line:
+
+ ```ruby
+ prometheus['listen_address'] = 'localhost:9090'
+ ```
+
+ Replace `localhost:9090` with the address/port you want Prometheus to
+ listen on.
+
+1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
+ take effect
+
+## Viewing performance metrics
+
+You can visit `http://localhost:9090` for the dashboard that Prometheus offers by default.
+
+>**Note:**
+If SSL has been enabled on your GitLab instance, you may not be able to access
+Prometheus on the same browser as GitLab due to [HSTS][hsts]. We plan to
+[provide access via GitLab][multi-user-prometheus], but in the interim there are
+some workarounds: using a separate browser for Prometheus, resetting HSTS, or
+having [Nginx proxy it][nginx-custom-config].
+
+The performance data collected by Prometheus can be viewed directly in the
+Prometheus console or through a compatible dashboard tool.
+The Prometheus interface provides a [flexible query language][prom-query] to work
+with the collected data where you can visualize their output.
+For a more fully featured dashboard, Grafana can be used and has
+[official support for Prometheus][prom-grafana].
+
+Sample Prometheus queries:
+
+- **% Memory used:** `(1 - ((node_memory_MemFree + node_memory_Cached) / node_memory_MemTotal)) * 100`
+- **% CPU load:** `1 - rate(node_cpu{mode="idle"}[5m])`
+- **Data transmitted:** `irate(node_network_transmit_bytes[5m])`
+- **Data received:** `irate(node_network_receive_bytes[5m])`
+
+## Configuring Prometheus to monitor Kubernetes
+
+> Introduced in GitLab 9.0.
+
+If your GitLab server is running within Kubernetes, Prometheus will collect metrics from the Nodes in the cluster including performance data on each container. This is particularly helpful if your CI/CD environments run in the same cluster, as you can use the [Prometheus project integration][] to monitor them.
+
+To disable the monitoring of Kubernetes:
+
+1. Edit `/etc/gitlab/gitlab.rb`
+1. Add or find and uncomment the following line and set it to `false`:
+
+ ```ruby
+ prometheus['monitor_kubernetes'] = false
+ ```
+
+1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
+ take effect
+
+## GitLab Prometheus metrics
+
+> Introduced as an experimental feature in GitLab 9.3.
+
+GitLab monitors its own internal service metrics, and makes them available at the `/-/metrics` endpoint. Unlike other exporters, this endpoint requires authentication as it is available on the same URL and port as user traffic.
+
+[➔ Read more about the GitLab Metrics.](gitlab_metrics.md)
+
+## Prometheus exporters
+
+There are a number of libraries and servers which help in exporting existing
+metrics from third-party systems as Prometheus metrics. This is useful for cases
+where it is not feasible to instrument a given system with Prometheus metrics
+directly (for example, HAProxy or Linux system stats). You can read more in the
+[Prometheus exporters and integrations upstream documentation][prom-exporters].
+
+While you can use any exporter you like with your GitLab installation, the
+following ones documented here are bundled in the Omnibus GitLab packages
+making it easy to configure and use.
+
+### Node exporter
+
+The node exporter allows you to measure various machine resources such as
+memory, disk and CPU utilization.
+
+[➔ Read more about the node exporter.](node_exporter.md)
+
+### Redis exporter
+
+The Redis exporter allows you to measure various Redis metrics.
+
+[➔ Read more about the Redis exporter.](redis_exporter.md)
+
+### Postgres exporter
+
+The Postgres exporter allows you to measure various PostgreSQL metrics.
+
+[➔ Read more about the Postgres exporter.](postgres_exporter.md)
+
+### GitLab monitor exporter
+
+The GitLab monitor exporter allows you to measure various GitLab metrics, pulled from Redis and the database.
+
+[➔ Read more about the GitLab monitor exporter.](gitlab_monitor_exporter.md)
+
+[grafana]: https://grafana.net
+[hsts]: https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
+[multi-user-prometheus]: https://gitlab.com/gitlab-org/multi-user-prometheus
+[nginx-custom-config]: https://docs.gitlab.com/omnibus/settings/nginx.html#inserting-custom-nginx-settings-into-the-gitlab-server-block
+[prometheus]: https://prometheus.io
+[prom-exporters]: https://prometheus.io/docs/instrumenting/exporters/
+[prom-query]: https://prometheus.io/docs/querying/basics
+[prom-grafana]: https://prometheus.io/docs/visualization/grafana/
+[scrape-config]: https://prometheus.io/docs/operating/configuration/#%3Cscrape_config%3E
+[reconfigure]: ../../restart_gitlab.md#omnibus-gitlab-reconfigure
+[1261]: https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/1261
+[prometheus integration]: ../../../user/project/integrations/prometheus.md
+[prometheus-cadvisor-metrics]: https://github.com/google/cadvisor/blob/master/docs/storage/prometheus.md
diff --git a/doc/administration/monitoring/prometheus/node_exporter.md b/doc/administration/monitoring/prometheus/node_exporter.md
new file mode 100644
index 00000000000..aef7758a88f
--- /dev/null
+++ b/doc/administration/monitoring/prometheus/node_exporter.md
@@ -0,0 +1,30 @@
+# Node exporter
+
+>**Note:**
+Available since Omnibus GitLab 8.16. For installations from source you'll
+have to install and configure it yourself.
+
+The [node exporter] allows you to measure various machine resources such as
+memory, disk and CPU utilization.
+
+To enable the node exporter:
+
+1. [Enable Prometheus](index.md#configuring-prometheus)
+1. Edit `/etc/gitlab/gitlab.rb`
+1. Add or find and uncomment the following line, making sure it's set to `true`:
+
+ ```ruby
+ node_exporter['enable'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
+ take effect
+
+Prometheus will now automatically begin collecting performance data from
+the node exporter exposed under `localhost:9100`.
+
+[← Back to the main Prometheus page](index.md)
+
+[node exporter]: https://github.com/prometheus/node_exporter
+[prometheus]: https://prometheus.io
+[reconfigure]: ../../restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/administration/monitoring/prometheus/postgres_exporter.md b/doc/administration/monitoring/prometheus/postgres_exporter.md
new file mode 100644
index 00000000000..8e2d3162f88
--- /dev/null
+++ b/doc/administration/monitoring/prometheus/postgres_exporter.md
@@ -0,0 +1,30 @@
+# Postgres exporter
+
+>**Note:**
+Available since [Omnibus GitLab 8.17][1131]. For installations from source
+you'll have to install and configure it yourself.
+
+The [postgres exporter] allows you to measure various PostgreSQL metrics.
+
+To enable the postgres exporter:
+
+1. [Enable Prometheus](index.md#configuring-prometheus)
+1. Edit `/etc/gitlab/gitlab.rb`
+1. Add or find and uncomment the following line, making sure it's set to `true`:
+
+ ```ruby
+ postgres_exporter['enable'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
+ take effect
+
+Prometheus will now automatically begin collecting performance data from
+the postgres exporter exposed under `localhost:9187`.
+
+[← Back to the main Prometheus page](index.md)
+
+[1131]: https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/1131
+[postgres exporter]: https://github.com/wrouesnel/postgres_exporter
+[prometheus]: https://prometheus.io
+[reconfigure]: ../../restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/administration/monitoring/prometheus/redis_exporter.md b/doc/administration/monitoring/prometheus/redis_exporter.md
new file mode 100644
index 00000000000..d54d409dbb6
--- /dev/null
+++ b/doc/administration/monitoring/prometheus/redis_exporter.md
@@ -0,0 +1,33 @@
+# Redis exporter
+
+>**Note:**
+Available since [Omnibus GitLab 8.17][1118]. For installations from source
+you'll have to install and configure it yourself.
+
+The [Redis exporter] allows you to measure various [Redis] metrics. For more
+information on what's exported [read the upstream documentation][redis-exp].
+
+To enable the Redis exporter:
+
+1. [Enable Prometheus](index.md#configuring-prometheus)
+1. Edit `/etc/gitlab/gitlab.rb`
+1. Add or find and uncomment the following line, making sure it's set to `true`:
+
+ ```ruby
+ redis_exporter['enable'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
+ take effect
+
+Prometheus will now automatically begin collecting performance data from
+the Redis exporter exposed under `localhost:9121`.
+
+[← Back to the main Prometheus page](index.md)
+
+[1118]: https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/1118
+[redis]: https://redis.io
+[redis exporter]: https://github.com/oliver006/redis_exporter
+[redis-exp]: https://github.com/oliver006/redis_exporter/blob/master/README.md#whats-exported
+[prometheus]: https://prometheus.io
+[reconfigure]: ../../restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/administration/operations.md b/doc/administration/operations.md
new file mode 100644
index 00000000000..0daceb98d99
--- /dev/null
+++ b/doc/administration/operations.md
@@ -0,0 +1,7 @@
+# GitLab operations
+
+- [Sidekiq MemoryKiller](operations/sidekiq_memory_killer.md)
+- [Sidekiq Job throttling](operations/sidekiq_job_throttling.md)
+- [Cleaning up Redis sessions](operations/cleaning_up_redis_sessions.md)
+- [Understanding Unicorn and unicorn-worker-killer](operations/unicorn.md)
+- [Moving repositories to a new location](operations/moving_repositories.md)
diff --git a/doc/administration/operations/cleaning_up_redis_sessions.md b/doc/administration/operations/cleaning_up_redis_sessions.md
new file mode 100644
index 00000000000..93521e976d5
--- /dev/null
+++ b/doc/administration/operations/cleaning_up_redis_sessions.md
@@ -0,0 +1,52 @@
+# Cleaning up stale Redis sessions
+
+Since version 6.2, GitLab stores web user sessions as key-value pairs in Redis.
+Prior to GitLab 7.3, user sessions did not automatically expire from Redis. If
+you have been running a large GitLab server (thousands of users) since before
+GitLab 7.3 we recommend cleaning up stale sessions to compact the Redis
+database after you upgrade to GitLab 7.3. You can also perform a cleanup while
+still running GitLab 7.2 or older, but in that case new stale sessions will
+start building up again after you clean up.
+
+In GitLab versions prior to 7.3.0, the session keys in Redis are 16-byte
+hexadecimal values such as '976aa289e2189b17d7ef525a6702ace9'. Starting with
+GitLab 7.3.0, the keys are
+prefixed with 'session:gitlab:', so they would look like
+'session:gitlab:976aa289e2189b17d7ef525a6702ace9'. Below we describe how to
+remove the keys in the old format.
+
+First we define a shell function with the proper Redis connection details.
+
+```
+rcli() {
+ # This example works for Omnibus installations of GitLab 7.3 or newer. For an
+ # installation from source you will have to change the socket path and the
+ # path to redis-cli.
+ sudo /opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.socket "$@"
+}
+
+# test the new shell function; the response should be PONG
+rcli ping
+```
+
+Now we do a search to see if there are any session keys in the old format for
+us to clean up.
+
+```
+# returns the number of old-format session keys in Redis
+rcli keys '*' | grep '^[a-f0-9]\{32\}$' | wc -l
+```
+
+If the number is larger than zero, you can proceed to expire the keys from
+Redis. If the number is zero there is nothing to clean up.
+
+```
+# Tell Redis to expire each matched key after 600 seconds.
+rcli keys '*' | grep '^[a-f0-9]\{32\}$' | awk '{ print "expire", $0, 600 }' | rcli
+# This will print '(integer) 1' for each key that gets expired.
+```
+
+Over the next 15 minutes (10 minutes expiry time plus 5 minutes Redis
+background save interval) your Redis database will be compacted. If you are
+still using GitLab 7.2, users who are not clicking around in GitLab during the
+10 minute expiry window will be signed out of GitLab.
diff --git a/doc/administration/operations/img/sidekiq_job_throttling.png b/doc/administration/operations/img/sidekiq_job_throttling.png
new file mode 100644
index 00000000000..dcf40b4bf17
--- /dev/null
+++ b/doc/administration/operations/img/sidekiq_job_throttling.png
Binary files differ
diff --git a/doc/administration/operations/moving_repositories.md b/doc/administration/operations/moving_repositories.md
new file mode 100644
index 00000000000..54adb99386a
--- /dev/null
+++ b/doc/administration/operations/moving_repositories.md
@@ -0,0 +1,180 @@
+# Moving repositories managed by GitLab
+
+Sometimes you need to move all repositories managed by GitLab to
+another filesystem or another server. In this document we will look
+at some of the ways you can copy all your repositories from
+`/var/opt/gitlab/git-data/repositories` to `/mnt/gitlab/repositories`.
+
+We will look at three scenarios: the target directory is empty, the
+target directory contains an outdated copy of the repositories, and
+how to deal with thousands of repositories.
+
+**Each of the approaches we list can/will overwrite data in the
+target directory `/mnt/gitlab/repositories`. Do not mix up the
+source and the target.**
+
+## Target directory is empty: use a tar pipe
+
+If the target directory `/mnt/gitlab/repositories` is empty the
+simplest thing to do is to use a tar pipe. This method has low
+overhead and tar is almost always already installed on your system.
+However, it is not possible to resume an interrupted tar pipe: if
+that happens then all data must be copied again.
+
+```
+# As the git user
+tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
+ tar -C /mnt/gitlab/repositories -xf -
+```
+
+If you want to see progress, replace `-xf` with `-xvf`.
+
+### Tar pipe to another server
+
+You can also use a tar pipe to copy data to another server. If your
+'git' user has SSH access to the newserver as 'git@newserver', you
+can pipe the data through SSH.
+
+```
+# As the git user
+tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
+ ssh git@newserver tar -C /mnt/gitlab/repositories -xf -
+```
+
+If you want to compress the data before it goes over the network
+(which will cost you CPU cycles) you can replace `ssh` with `ssh -C`.
+
+## The target directory contains an outdated copy of the repositories: use rsync
+
+If the target directory already contains a partial / outdated copy
+of the repositories it may be wasteful to copy all the data again
+with tar. In this scenario it is better to use rsync. This utility
+is either already installed on your system or easily installable
+via apt, yum etc.
+
+```
+# As the 'git' user
+rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
+ /mnt/gitlab/repositories
+```
+
+The `/.` in the command above is very important, without it you can
+easily get the wrong directory structure in the target directory.
+If you want to see progress, replace `-a` with `-av`.
+
+### Single rsync to another server
+
+If the 'git' user on your source system has SSH access to the target
+server you can send the repositories over the network with rsync.
+
+```
+# As the 'git' user
+rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
+ git@newserver:/mnt/gitlab/repositories
+```
+
+## Thousands of Git repositories: use one rsync per repository
+
+Every time you start an rsync job it has to inspect all files in
+the source directory, all files in the target directory, and then
+decide what files to copy or not. If the source or target directory
+has many contents this startup phase of rsync can become a burden
+for your GitLab server. In cases like this you can make rsync's
+life easier by dividing its work in smaller pieces, and sync one
+repository at a time.
+
+In addition to rsync we will use [GNU
+Parallel](http://www.gnu.org/software/parallel/). This utility is
+not included in GitLab so you need to install it yourself with apt
+or yum. Also note that the GitLab scripts we used below were added
+in GitLab 8.1.
+
+** This process does not clean up repositories at the target location that no
+longer exist at the source. ** If you start using your GitLab instance with
+`/mnt/gitlab/repositories`, you need to run `gitlab-rake gitlab:cleanup:repos`
+after switching to the new repository storage directory.
+
+### Parallel rsync for all repositories known to GitLab
+
+This will sync repositories with 10 rsync processes at a time. We keep
+track of progress so that the transfer can be restarted if necessary.
+
+First we create a new directory, owned by 'git', to hold transfer
+logs. We assume the directory is empty before we start the transfer
+procedure, and that we are the only ones writing files in it.
+
+```
+# Omnibus
+sudo mkdir /var/opt/gitlab/transfer-logs
+sudo chown git:git /var/opt/gitlab/transfer-logs
+
+# Source
+sudo -u git -H mkdir /home/git/transfer-logs
+```
+
+We seed the process with a list of the directories we want to copy.
+
+```
+# Omnibus
+sudo -u git sh -c 'gitlab-rake gitlab:list_repos > /var/opt/gitlab/transfer-logs/all-repos-$(date +%s).txt'
+
+# Source
+cd /home/git/gitlab
+sudo -u git -H sh -c 'bundle exec rake gitlab:list_repos > /home/git/transfer-logs/all-repos-$(date +%s).txt'
+```
+
+Now we can start the transfer. The command below is idempotent, and
+the number of jobs done by GNU Parallel should converge to zero. If it
+does not some repositories listed in all-repos-1234.txt may have been
+deleted/renamed before they could be copied.
+
+```
+# Omnibus
+sudo -u git sh -c '
+cat /var/opt/gitlab/transfer-logs/* | sort | uniq -u |\
+ /usr/bin/env JOBS=10 \
+ /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \
+ /var/opt/gitlab/transfer-logs/success-$(date +%s).log \
+ /var/opt/gitlab/git-data/repositories \
+ /mnt/gitlab/repositories
+'
+
+# Source
+cd /home/git/gitlab
+sudo -u git -H sh -c '
+cat /home/git/transfer-logs/* | sort | uniq -u |\
+ /usr/bin/env JOBS=10 \
+ bin/parallel-rsync-repos \
+ /home/git/transfer-logs/success-$(date +%s).log \
+ /home/git/repositories \
+ /mnt/gitlab/repositories
+`
+```
+
+### Parallel rsync only for repositories with recent activity
+
+Suppose you have already done one sync that started after 2015-10-1 12:00 UTC.
+Then you might only want to sync repositories that were changed via GitLab
+_after_ that time. You can use the 'SINCE' variable to tell 'rake
+gitlab:list_repos' to only print repositories with recent activity.
+
+```
+# Omnibus
+sudo gitlab-rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\
+ sudo -u git \
+ /usr/bin/env JOBS=10 \
+ /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \
+ success-$(date +%s).log \
+ /var/opt/gitlab/git-data/repositories \
+ /mnt/gitlab/repositories
+
+# Source
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\
+ sudo -u git -H \
+ /usr/bin/env JOBS=10 \
+ bin/parallel-rsync-repos \
+ success-$(date +%s).log \
+ /home/git/repositories \
+ /mnt/gitlab/repositories
+```
diff --git a/doc/administration/operations/sidekiq_job_throttling.md b/doc/administration/operations/sidekiq_job_throttling.md
new file mode 100644
index 00000000000..ddeaa22e288
--- /dev/null
+++ b/doc/administration/operations/sidekiq_job_throttling.md
@@ -0,0 +1,33 @@
+# Sidekiq Job throttling
+
+> Note: Introduced with GitLab 8.14
+
+When your GitLab installation needs to handle tens of thousands of background
+jobs, it can be convenient to throttle queues that do not need to be executed
+immediately, e.g. long running jobs like Pipelines, thus allowing jobs that do
+need to be executed immediately to have access to more resources.
+
+In order to accomplish this, you can limit the amount of workers that certain
+slow running queues can have available. This is what we call Sidekiq Job
+Throttling. Depending on your infrastructure, you might have different slow
+running queues, which is why you can choose which queues you want to throttle
+and by how much you want to throttle them.
+
+These settings are available in the Application Settings of your GitLab
+installation.
+
+![Sidekiq Job Throttling](img/sidekiq_job_throttling.png)
+
+The throttle factor determines the maximum number of workers a queue can run on.
+This value gets multiplied by `:concurrency` value set in the Sidekiq settings
+and rounded up to the closest full integer.
+
+So, for example, you set the `:concurrency` to 25 and the `Throttling factor` to
+0.1, the maximum workers assigned to the selected queues would be 3.
+
+```ruby
+queue_limit = (factor * Sidekiq.options[:concurrency]).ceil
+```
+
+After enabling the job throttling, you will need to restart your GitLab
+instance, in order for the changes to take effect. \ No newline at end of file
diff --git a/doc/administration/operations/sidekiq_memory_killer.md b/doc/administration/operations/sidekiq_memory_killer.md
new file mode 100644
index 00000000000..b5e78348989
--- /dev/null
+++ b/doc/administration/operations/sidekiq_memory_killer.md
@@ -0,0 +1,40 @@
+# Sidekiq MemoryKiller
+
+The GitLab Rails application code suffers from memory leaks. For web requests
+this problem is made manageable using
+[unicorn-worker-killer](https://github.com/kzk/unicorn-worker-killer) which
+restarts Unicorn worker processes in between requests when needed. The Sidekiq
+MemoryKiller applies the same approach to the Sidekiq processes used by GitLab
+to process background jobs.
+
+Unlike unicorn-worker-killer, which is enabled by default for all GitLab
+installations since GitLab 6.4, the Sidekiq MemoryKiller is enabled by default
+_only_ for Omnibus packages. The reason for this is that the MemoryKiller
+relies on Runit to restart Sidekiq after a memory-induced shutdown and GitLab
+installations from source do not all use Runit or an equivalent.
+
+With the default settings, the MemoryKiller will cause a Sidekiq restart no
+more often than once every 15 minutes, with the restart causing about one
+minute of delay for incoming background jobs.
+
+## Configuring the MemoryKiller
+
+The MemoryKiller is controlled using environment variables.
+
+- `SIDEKIQ_MEMORY_KILLER_MAX_RSS`: if this variable is set, and its value is
+ greater than 0, then after each Sidekiq job, the MemoryKiller will check the
+ RSS of the Sidekiq process that executed the job. If the RSS of the Sidekiq
+ process (expressed in kilobytes) exceeds SIDEKIQ_MEMORY_KILLER_MAX_RSS, a
+ delayed shutdown is triggered. The default value for Omnibus packages is set
+ [in the omnibus-gitlab
+ repository](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/attributes/default.rb).
+- `SIDEKIQ_MEMORY_KILLER_GRACE_TIME`: defaults 900 seconds (15 minutes). When
+ a shutdown is triggered, the Sidekiq process will keep working normally for
+ another 15 minutes.
+- `SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT`: defaults to 30 seconds. When the grace
+ time has expired, the MemoryKiller tells Sidekiq to stop accepting new jobs.
+ Existing jobs get 30 seconds to finish. After that, the MemoryKiller tells
+ Sidekiq to shut down, and an external supervision mechanism (e.g. Runit) must
+ restart Sidekiq.
+- `SIDEKIQ_MEMORY_KILLER_SHUTDOWN_SIGNAL`: defaults to `SIGKILL`. The name of
+ the final signal sent to the Sidekiq process when we want it to shut down.
diff --git a/doc/administration/operations/unicorn.md b/doc/administration/operations/unicorn.md
new file mode 100644
index 00000000000..bad61151bda
--- /dev/null
+++ b/doc/administration/operations/unicorn.md
@@ -0,0 +1,86 @@
+# Understanding Unicorn and unicorn-worker-killer
+
+## Unicorn
+
+GitLab uses [Unicorn](http://unicorn.bogomips.org/), a pre-forking Ruby web
+server, to handle web requests (web browsers and Git HTTP clients). Unicorn is
+a daemon written in Ruby and C that can load and run a Ruby on Rails
+application; in our case the Rails application is GitLab Community Edition or
+GitLab Enterprise Edition.
+
+Unicorn has a multi-process architecture to make better use of available CPU
+cores (processes can run on different cores) and to have stronger fault
+tolerance (most failures stay isolated in only one process and cannot take down
+GitLab entirely). On startup, the Unicorn 'master' process loads a clean Ruby
+environment with the GitLab application code, and then spawns 'workers' which
+inherit this clean initial environment. The 'master' never handles any
+requests, that is left to the workers. The operating system network stack
+queues incoming requests and distributes them among the workers.
+
+In a perfect world, the master would spawn its pool of workers once, and then
+the workers handle incoming web requests one after another until the end of
+time. In reality, worker processes can crash or time out: if the master notices
+that a worker takes too long to handle a request it will terminate the worker
+process with SIGKILL ('kill -9'). No matter how the worker process ended, the
+master process will replace it with a new 'clean' process again. Unicorn is
+designed to be able to replace 'crashed' workers without dropping user
+requests.
+
+This is what a Unicorn worker timeout looks like in `unicorn_stderr.log`. The
+master process has PID 56227 below.
+
+```
+[2015-06-05T10:58:08.660325 #56227] ERROR -- : worker=10 PID:53009 timeout (61s > 60s), killing
+[2015-06-05T10:58:08.699360 #56227] ERROR -- : reaped #<Process::Status: pid 53009 SIGKILL (signal 9)> worker=10
+[2015-06-05T10:58:08.708141 #62538] INFO -- : worker=10 spawned pid=62538
+[2015-06-05T10:58:08.708824 #62538] INFO -- : worker=10 ready
+```
+
+### Tunables
+
+The main tunables for Unicorn are the number of worker processes and the
+request timeout after which the Unicorn master terminates a worker process.
+See the [omnibus-gitlab Unicorn settings
+documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/unicorn.md)
+if you want to adjust these settings.
+
+## unicorn-worker-killer
+
+GitLab has memory leaks. These memory leaks manifest themselves in long-running
+processes, such as Unicorn workers. (The Unicorn master process is not known to
+leak memory, probably because it does not handle user requests.)
+
+To make these memory leaks manageable, GitLab comes with the
+[unicorn-worker-killer gem](https://github.com/kzk/unicorn-worker-killer). This
+gem [monkey-patches](https://en.wikipedia.org/wiki/Monkey_patch) the Unicorn
+workers to do a memory self-check after every 16 requests. If the memory of the
+Unicorn worker exceeds a pre-set limit then the worker process exits. The
+Unicorn master then automatically replaces the worker process.
+
+This is a robust way to handle memory leaks: Unicorn is designed to handle
+workers that 'crash' so no user requests will be dropped. The
+unicorn-worker-killer gem is designed to only terminate a worker process _in
+between requests_, so no user requests are affected.
+
+This is what a Unicorn worker memory restart looks like in unicorn_stderr.log.
+You see that worker 4 (PID 125918) is inspecting itself and decides to exit.
+The threshold memory value was 254802235 bytes, about 250MB. With GitLab this
+threshold is a random value between 200 and 250 MB. The master process (PID
+117565) then reaps the worker process and spawns a new 'worker 4' with PID
+127549.
+
+```
+[2015-06-05T12:07:41.828374 #125918] WARN -- : #<Unicorn::HttpServer:0x00000002734770>: worker (pid: 125918) exceeds memory limit (256413696 bytes > 254802235 bytes)
+[2015-06-05T12:07:41.828472 #125918] WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 125918) alive: 23 sec (trial 1)
+[2015-06-05T12:07:42.025916 #117565] INFO -- : reaped #<Process::Status: pid 125918 exit 0> worker=4
+[2015-06-05T12:07:42.034527 #127549] INFO -- : worker=4 spawned pid=127549
+[2015-06-05T12:07:42.035217 #127549] INFO -- : worker=4 ready
+```
+
+One other thing that stands out in the log snippet above, taken from
+GitLab.com, is that 'worker 4' was serving requests for only 23 seconds. This
+is a normal value for our current GitLab.com setup and traffic.
+
+The high frequency of Unicorn memory restarts on some GitLab sites can be a
+source of confusion for administrators. Usually they are a [red
+herring](https://en.wikipedia.org/wiki/Red_herring).
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
new file mode 100644
index 00000000000..0c63b0b59a7
--- /dev/null
+++ b/doc/administration/pages/index.md
@@ -0,0 +1,283 @@
+# GitLab Pages administration
+
+> **Notes:**
+- [Introduced][ee-80] in GitLab EE 8.3.
+- Custom CNAMEs with TLS support were [introduced][ee-173] in GitLab EE 8.5.
+- GitLab Pages [were ported][ce-14605] to Community Edition in GitLab 8.17.
+- This guide is for Omnibus GitLab installations. If you have installed
+ GitLab from source, follow the [Pages source installation document](source.md).
+- To learn how to use GitLab Pages, read the [user documentation][pages-userguide].
+
+---
+
+This document describes how to set up the _latest_ GitLab Pages feature. Make
+sure to read the [changelog](#changelog) if you are upgrading to a new GitLab
+version as it may include new features and changes needed to be made in your
+configuration.
+
+## Overview
+
+GitLab Pages makes use of the [GitLab Pages daemon], a simple HTTP server
+written in Go that can listen on an external IP address and provide support for
+custom domains and custom certificates. It supports dynamic certificates through
+SNI and exposes pages using HTTP2 by default.
+You are encouraged to read its [README][pages-readme] to fully understand how
+it works.
+
+---
+
+In the case of [custom domains](#custom-domains) (but not
+[wildcard domains](#wildcard-domains)), the Pages daemon needs to listen on
+ports `80` and/or `443`. For that reason, there is some flexibility in the way
+which you can set it up:
+
+1. Run the Pages daemon in the same server as GitLab, listening on a secondary IP.
+1. Run the Pages daemon in a separate server. In that case, the
+ [Pages path](#change-storage-path) must also be present in the server that
+ the Pages daemon is installed, so you will have to share it via network.
+1. Run the Pages daemon in the same server as GitLab, listening on the same IP
+ but on different ports. In that case, you will have to proxy the traffic with
+ a loadbalancer. If you choose that route note that you should use TCP load
+ balancing for HTTPS. If you use TLS-termination (HTTPS-load balancing) the
+ pages will not be able to be served with user provided certificates. For
+ HTTP it's OK to use HTTP or TCP load balancing.
+
+In this document, we will proceed assuming the first option. If you are not
+supporting custom domains a secondary IP is not needed.
+
+## Prerequisites
+
+Before proceeding with the Pages configuration, you will need to:
+
+1. Have a separate domain under which the GitLab Pages will be served. In this
+ document we assume that to be `example.io`.
+1. Configure a **wildcard DNS record**.
+1. (Optional) Have a **wildcard certificate** for that domain if you decide to
+ serve Pages under HTTPS.
+1. (Optional but recommended) Enable [Shared runners](../../ci/runners/README.md)
+ so that your users don't have to bring their own.
+1. (Only for custom domains) Have a **secondary IP**.
+
+### DNS configuration
+
+GitLab Pages expect to run on their own virtual host. In your DNS server/provider
+you need to add a [wildcard DNS A record][wiki-wildcard-dns] pointing to the
+host that GitLab runs. For example, an entry would look like this:
+
+```
+*.example.io. 1800 IN A 1.1.1.1
+*.example.io. 1800 IN AAAA 2001::1
+```
+
+where `example.io` is the domain under which GitLab Pages will be served
+and `1.1.1.1` is the IPv4 address of your GitLab instance and `2001::1` is the
+IPv6 address. If you don't have IPv6, you can omit the AAAA record.
+
+> **Note:**
+You should not use the GitLab domain to serve user pages. For more information
+see the [security section](#security).
+
+[wiki-wildcard-dns]: https://en.wikipedia.org/wiki/Wildcard_DNS_record
+
+## Configuration
+
+Depending on your needs, you can set up GitLab Pages in 4 different ways.
+The following options are listed from the easiest setup to the most
+advanced one. The absolute minimum requirement is to set up the wildcard DNS
+since that is needed in all configurations.
+
+### Wildcard domains
+
+>**Requirements:**
+- [Wildcard DNS setup](#dns-configuration)
+>
+>---
+>
+URL scheme: `http://page.example.io`
+
+This is the minimum setup that you can use Pages with. It is the base for all
+other setups as described below. Nginx will proxy all requests to the daemon.
+The Pages daemon doesn't listen to the outside world.
+
+1. Set the external URL for GitLab Pages in `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ pages_external_url 'http://example.io'
+ ```
+
+1. [Reconfigure GitLab][reconfigure]
+
+Watch the [video tutorial][video-admin] for this configuration.
+
+### Wildcard domains with TLS support
+
+>**Requirements:**
+- [Wildcard DNS setup](#dns-configuration)
+- Wildcard TLS certificate
+>
+>---
+>
+URL scheme: `https://page.example.io`
+
+Nginx will proxy all requests to the daemon. Pages daemon doesn't listen to the
+outside world.
+
+1. Place the certificate and key inside `/etc/gitlab/ssl`
+1. In `/etc/gitlab/gitlab.rb` specify the following configuration:
+
+ ```ruby
+ pages_external_url 'https://example.io'
+
+ pages_nginx['redirect_http_to_https'] = true
+ pages_nginx['ssl_certificate'] = "/etc/gitlab/ssl/pages-nginx.crt"
+ pages_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/pages-nginx.key"
+ ```
+
+ where `pages-nginx.crt` and `pages-nginx.key` are the SSL cert and key,
+ respectively.
+
+1. [Reconfigure GitLab][reconfigure]
+
+## Advanced configuration
+
+In addition to the wildcard domains, you can also have the option to configure
+GitLab Pages to work with custom domains. Again, there are two options here:
+support custom domains with and without TLS certificates. The easiest setup is
+that without TLS certificates. In either case, you'll need a secondary IP. If
+you have IPv6 as well as IPv4 addresses, you can use them both.
+
+### Custom domains
+
+>**Requirements:**
+- [Wildcard DNS setup](#dns-configuration)
+- Secondary IP
+>
+---
+>
+URL scheme: `http://page.example.io` and `http://domain.com`
+
+In that case, the Pages daemon is running, Nginx still proxies requests to
+the daemon but the daemon is also able to receive requests from the outside
+world. Custom domains are supported, but no TLS.
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ pages_external_url "http://example.io"
+ nginx['listen_addresses'] = ['1.1.1.1']
+ pages_nginx['enable'] = false
+ gitlab_pages['external_http'] = ['1.1.1.2:80', '[2001::2]:80']
+ ```
+
+ where `1.1.1.1` is the primary IP address that GitLab is listening to and
+ `1.1.1.2` and `2001::2` are the secondary IPs the GitLab Pages daemon
+ listens on. If you don't have IPv6, you can omit the IPv6 address.
+
+1. [Reconfigure GitLab][reconfigure]
+
+### Custom domains with TLS support
+
+>**Requirements:**
+- [Wildcard DNS setup](#dns-configuration)
+- Wildcard TLS certificate
+- Secondary IP
+>
+---
+>
+URL scheme: `https://page.example.io` and `https://domain.com`
+
+In that case, the Pages daemon is running, Nginx still proxies requests to
+the daemon but the daemon is also able to receive requests from the outside
+world. Custom domains and TLS are supported.
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ pages_external_url "https://example.io"
+ nginx['listen_addresses'] = ['1.1.1.1']
+ pages_nginx['enable'] = false
+ gitlab_pages['cert'] = "/etc/gitlab/ssl/example.io.crt"
+ gitlab_pages['cert_key'] = "/etc/gitlab/ssl/example.io.key"
+ gitlab_pages['external_http'] = ['1.1.1.2:80', '[2001::2]:80']
+ gitlab_pages['external_https'] = ['1.1.1.2:443', '[2001::2]:443']
+ ```
+
+ where `1.1.1.1` is the primary IP address that GitLab is listening to and
+ `1.1.1.2` and `2001::2` are the secondary IPs where the GitLab Pages daemon
+ listens on. If you don't have IPv6, you can omit the IPv6 address.
+
+1. [Reconfigure GitLab][reconfigure]
+
+## Change storage path
+
+Follow the steps below to change the default path where GitLab Pages' contents
+are stored.
+
+1. Pages are stored by default in `/var/opt/gitlab/gitlab-rails/shared/pages`.
+ If you wish to store them in another location you must set it up in
+ `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['pages_path'] = "/mnt/storage/pages"
+ ```
+
+1. [Reconfigure GitLab][reconfigure]
+
+## Set maximum pages size
+
+The maximum size of the unpacked archive per project can be configured in the
+Admin area under the Application settings in the **Maximum size of pages (MB)**.
+The default is 100MB.
+
+## Backup
+
+Pages are part of the [regular backup][backup] so there is nothing to configure.
+
+## Security
+
+You should strongly consider running GitLab pages under a different hostname
+than GitLab to prevent XSS attacks.
+
+## Changelog
+
+GitLab Pages were first introduced in GitLab EE 8.3. Since then, many features
+where added, like custom CNAME and TLS support, and many more are likely to
+come. Below is a brief changelog. If no changes were introduced or a version is
+missing from the changelog, assume that the documentation is the same as the
+latest previous version.
+
+---
+
+**GitLab 8.17 ([documentation][8-17-docs])**
+
+- GitLab Pages were ported to Community Edition in GitLab 8.17.
+- Documentation was refactored to be more modular and easy to follow.
+
+**GitLab 8.5 ([documentation][8-5-docs])**
+
+- In GitLab 8.5 we introduced the [gitlab-pages][] daemon which is now the
+ recommended way to set up GitLab Pages.
+- The [NGINX configs][] have changed to reflect this change. So make sure to
+ update them.
+- Custom CNAME and TLS certificates support.
+- Documentation was moved to one place.
+
+**GitLab 8.3 ([documentation][8-3-docs])**
+
+- GitLab Pages feature was introduced.
+
+[8-3-docs]: https://gitlab.com/gitlab-org/gitlab-ee/blob/8-3-stable-ee/doc/pages/administration.md
+[8-5-docs]: https://gitlab.com/gitlab-org/gitlab-ee/blob/8-5-stable-ee/doc/pages/administration.md
+[8-17-docs]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-17-stable-ce/doc/administration/pages/index.md
+[backup]: ../../raketasks/backup_restore.md
+[ce-14605]: https://gitlab.com/gitlab-org/gitlab-ce/issues/14605
+[ee-80]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/80
+[ee-173]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/173
+[gitlab pages daemon]: https://gitlab.com/gitlab-org/gitlab-pages
+[NGINX configs]: https://gitlab.com/gitlab-org/gitlab-ee/tree/8-5-stable-ee/lib/support/nginx
+[pages-readme]: https://gitlab.com/gitlab-org/gitlab-pages/blob/master/README.md
+[pages-userguide]: ../../user/project/pages/index.md
+[reconfigure]: ../restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart]: ../restart_gitlab.md#installations-from-source
+[gitlab-pages]: https://gitlab.com/gitlab-org/gitlab-pages/tree/v0.2.4
+[video-admin]: https://youtu.be/dD8c7WNcc6s
diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md
new file mode 100644
index 00000000000..a45c3306457
--- /dev/null
+++ b/doc/administration/pages/source.md
@@ -0,0 +1,438 @@
+# GitLab Pages administration for source installations
+
+>**Note:**
+Before attempting to enable GitLab Pages, first make sure you have
+[installed GitLab](../../install/installation.md) successfully.
+
+This is the documentation for configuring a GitLab Pages when you have installed
+GitLab from source and not using the Omnibus packages.
+
+You are encouraged to read the [Omnibus documentation](index.md) as it provides
+some invaluable information to the configuration of GitLab Pages. Please proceed
+to read it before going forward with this guide.
+
+We also highly recommend that you use the Omnibus GitLab packages, as we
+optimize them specifically for GitLab, and we will take care of upgrading GitLab
+Pages to the latest supported version.
+
+## Overview
+
+GitLab Pages makes use of the [GitLab Pages daemon], a simple HTTP server
+written in Go that can listen on an external IP address and provide support for
+custom domains and custom certificates. It supports dynamic certificates through
+SNI and exposes pages using HTTP2 by default.
+You are encouraged to read its [README][pages-readme] to fully understand how
+it works.
+
+---
+
+In the case of [custom domains](#custom-domains) (but not
+[wildcard domains](#wildcard-domains)), the Pages daemon needs to listen on
+ports `80` and/or `443`. For that reason, there is some flexibility in the way
+which you can set it up:
+
+1. Run the Pages daemon in the same server as GitLab, listening on a secondary IP.
+1. Run the Pages daemon in a separate server. In that case, the
+ [Pages path](#change-storage-path) must also be present in the server that
+ the Pages daemon is installed, so you will have to share it via network.
+1. Run the Pages daemon in the same server as GitLab, listening on the same IP
+ but on different ports. In that case, you will have to proxy the traffic with
+ a loadbalancer. If you choose that route note that you should use TCP load
+ balancing for HTTPS. If you use TLS-termination (HTTPS-load balancing) the
+ pages will not be able to be served with user provided certificates. For
+ HTTP it's OK to use HTTP or TCP load balancing.
+
+In this document, we will proceed assuming the first option. If you are not
+supporting custom domains a secondary IP is not needed.
+
+## Prerequisites
+
+Before proceeding with the Pages configuration, make sure that:
+
+1. You have a separate domain under which GitLab Pages will be served. In
+ this document we assume that to be `example.io`.
+1. You have configured a **wildcard DNS record** for that domain.
+1. You have installed the `zip` and `unzip` packages in the same server that
+ GitLab is installed since they are needed to compress/uncompress the
+ Pages artifacts.
+1. (Optional) You have a **wildcard certificate** for the Pages domain if you
+ decide to serve Pages (`*.example.io`) under HTTPS.
+1. (Optional but recommended) You have configured and enabled the [Shared Runners][]
+ so that your users don't have to bring their own.
+
+### DNS configuration
+
+GitLab Pages expect to run on their own virtual host. In your DNS server/provider
+you need to add a [wildcard DNS A record][wiki-wildcard-dns] pointing to the
+host that GitLab runs. For example, an entry would look like this:
+
+```
+*.example.io. 1800 IN A 1.1.1.1
+```
+
+where `example.io` is the domain under which GitLab Pages will be served
+and `1.1.1.1` is the IP address of your GitLab instance.
+
+> **Note:**
+You should not use the GitLab domain to serve user pages. For more information
+see the [security section](#security).
+
+[wiki-wildcard-dns]: https://en.wikipedia.org/wiki/Wildcard_DNS_record
+
+## Configuration
+
+Depending on your needs, you can set up GitLab Pages in 4 different ways.
+The following options are listed from the easiest setup to the most
+advanced one. The absolute minimum requirement is to set up the wildcard DNS
+since that is needed in all configurations.
+
+### Wildcard domains
+
+>**Requirements:**
+- [Wildcard DNS setup](#dns-configuration)
+>
+>---
+>
+URL scheme: `http://page.example.io`
+
+This is the minimum setup that you can use Pages with. It is the base for all
+other setups as described below. Nginx will proxy all requests to the daemon.
+The Pages daemon doesn't listen to the outside world.
+
+1. Install the Pages daemon:
+
+ ```
+ cd /home/git
+ sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-pages.git
+ cd gitlab-pages
+ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
+ sudo -u git -H make
+ ```
+
+1. Go to the GitLab installation directory:
+
+ ```bash
+ cd /home/git/gitlab
+ ```
+
+1. Edit `gitlab.yml` and under the `pages` setting, set `enabled` to `true` and
+ the `host` to the FQDN under which GitLab Pages will be served:
+
+ ```yaml
+ ## GitLab Pages
+ pages:
+ enabled: true
+ # The location where pages are stored (default: shared/pages).
+ # path: shared/pages
+
+ host: example.io
+ port: 80
+ https: false
+ ```
+
+1. Edit `/etc/default/gitlab` and set `gitlab_pages_enabled` to `true` in
+ order to enable the pages daemon. In `gitlab_pages_options` the
+ `-pages-domain` must match the `host` setting that you set above.
+
+ ```
+ gitlab_pages_enabled=true
+ gitlab_pages_options="-pages-domain example.io -pages-root $app_root/shared/pages -listen-proxy 127.0.0.1:8090
+ ```
+
+1. Copy the `gitlab-pages` Nginx configuration file:
+
+ ```bash
+ sudo cp lib/support/nginx/gitlab-pages /etc/nginx/sites-available/gitlab-pages.conf
+ sudo ln -sf /etc/nginx/sites-{available,enabled}/gitlab-pages.conf
+ ```
+
+1. Restart NGINX
+1. [Restart GitLab][restart]
+
+### Wildcard domains with TLS support
+
+>**Requirements:**
+- [Wildcard DNS setup](#dns-configuration)
+- Wildcard TLS certificate
+>
+>---
+>
+URL scheme: `https://page.example.io`
+
+Nginx will proxy all requests to the daemon. Pages daemon doesn't listen to the
+outside world.
+
+1. Install the Pages daemon:
+
+ ```
+ cd /home/git
+ sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-pages.git
+ cd gitlab-pages
+ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
+ sudo -u git -H make
+ ```
+
+1. In `gitlab.yml`, set the port to `443` and https to `true`:
+
+ ```bash
+ ## GitLab Pages
+ pages:
+ enabled: true
+ # The location where pages are stored (default: shared/pages).
+ # path: shared/pages
+
+ host: example.io
+ port: 443
+ https: true
+ ```
+
+1. Edit `/etc/default/gitlab` and set `gitlab_pages_enabled` to `true` in
+ order to enable the pages daemon. In `gitlab_pages_options` the
+ `-pages-domain` must match the `host` setting that you set above.
+ The `-root-cert` and `-root-key` settings are the wildcard TLS certificates
+ of the `example.io` domain:
+
+ ```
+ gitlab_pages_enabled=true
+ gitlab_pages_options="-pages-domain example.io -pages-root $app_root/shared/pages -listen-proxy 127.0.0.1:8090 -root-cert /path/to/example.io.crt -root-key /path/to/example.io.key
+ ```
+
+1. Copy the `gitlab-pages-ssl` Nginx configuration file:
+
+ ```bash
+ sudo cp lib/support/nginx/gitlab-pages-ssl /etc/nginx/sites-available/gitlab-pages-ssl.conf
+ sudo ln -sf /etc/nginx/sites-{available,enabled}/gitlab-pages-ssl.conf
+ ```
+
+1. Restart NGINX
+1. [Restart GitLab][restart]
+
+## Advanced configuration
+
+In addition to the wildcard domains, you can also have the option to configure
+GitLab Pages to work with custom domains. Again, there are two options here:
+support custom domains with and without TLS certificates. The easiest setup is
+that without TLS certificates.
+
+### Custom domains
+
+>**Requirements:**
+- [Wildcard DNS setup](#dns-configuration)
+- Secondary IP
+>
+---
+>
+URL scheme: `http://page.example.io` and `http://domain.com`
+
+In that case, the pages daemon is running, Nginx still proxies requests to
+the daemon but the daemon is also able to receive requests from the outside
+world. Custom domains are supported, but no TLS.
+
+1. Install the Pages daemon:
+
+ ```
+ cd /home/git
+ sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-pages.git
+ cd gitlab-pages
+ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
+ sudo -u git -H make
+ ```
+
+1. Edit `gitlab.yml` to look like the example below. You need to change the
+ `host` to the FQDN under which GitLab Pages will be served. Set
+ `external_http` to the secondary IP on which the pages daemon will listen
+ for connections:
+
+ ```yaml
+ pages:
+ enabled: true
+ # The location where pages are stored (default: shared/pages).
+ # path: shared/pages
+
+ host: example.io
+ port: 80
+ https: false
+
+ external_http: 1.1.1.2:80
+ ```
+
+1. Edit `/etc/default/gitlab` and set `gitlab_pages_enabled` to `true` in
+ order to enable the pages daemon. In `gitlab_pages_options` the
+ `-pages-domain` and `-listen-http` must match the `host` and `external_http`
+ settings that you set above respectively:
+
+ ```
+ gitlab_pages_enabled=true
+ gitlab_pages_options="-pages-domain example.io -pages-root $app_root/shared/pages -listen-proxy 127.0.0.1:8090 -listen-http 1.1.1.2:80"
+ ```
+
+1. Copy the `gitlab-pages-ssl` Nginx configuration file:
+
+ ```bash
+ sudo cp lib/support/nginx/gitlab-pages /etc/nginx/sites-available/gitlab-pages.conf
+ sudo ln -sf /etc/nginx/sites-{available,enabled}/gitlab-pages.conf
+ ```
+
+1. Edit all GitLab related configs in `/etc/nginx/site-available/` and replace
+ `0.0.0.0` with `1.1.1.1`, where `1.1.1.1` the primary IP where GitLab
+ listens to.
+1. Restart NGINX
+1. [Restart GitLab][restart]
+
+### Custom domains with TLS support
+
+>**Requirements:**
+- [Wildcard DNS setup](#dns-configuration)
+- Wildcard TLS certificate
+- Secondary IP
+>
+---
+>
+URL scheme: `https://page.example.io` and `https://domain.com`
+
+In that case, the pages daemon is running, Nginx still proxies requests to
+the daemon but the daemon is also able to receive requests from the outside
+world. Custom domains and TLS are supported.
+
+1. Install the Pages daemon:
+
+ ```
+ cd /home/git
+ sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-pages.git
+ cd gitlab-pages
+ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
+ sudo -u git -H make
+ ```
+
+1. Edit `gitlab.yml` to look like the example below. You need to change the
+ `host` to the FQDN under which GitLab Pages will be served. Set
+ `external_http` and `external_https` to the secondary IP on which the pages
+ daemon will listen for connections:
+
+ ```yaml
+ ## GitLab Pages
+ pages:
+ enabled: true
+ # The location where pages are stored (default: shared/pages).
+ # path: shared/pages
+
+ host: example.io
+ port: 443
+ https: true
+
+ external_http: 1.1.1.2:80
+ external_https: 1.1.1.2:443
+ ```
+
+1. Edit `/etc/default/gitlab` and set `gitlab_pages_enabled` to `true` in
+ order to enable the pages daemon. In `gitlab_pages_options` the
+ `-pages-domain`, `-listen-http` and `-listen-https` must match the `host`,
+ `external_http` and `external_https` settings that you set above respectively.
+ The `-root-cert` and `-root-key` settings are the wildcard TLS certificates
+ of the `example.io` domain:
+
+ ```
+ gitlab_pages_enabled=true
+ gitlab_pages_options="-pages-domain example.io -pages-root $app_root/shared/pages -listen-proxy 127.0.0.1:8090 -listen-http 1.1.1.2:80 -listen-https 1.1.1.2:443 -root-cert /path/to/example.io.crt -root-key /path/to/example.io.key
+ ```
+
+1. Copy the `gitlab-pages-ssl` Nginx configuration file:
+
+ ```bash
+ sudo cp lib/support/nginx/gitlab-pages-ssl /etc/nginx/sites-available/gitlab-pages-ssl.conf
+ sudo ln -sf /etc/nginx/sites-{available,enabled}/gitlab-pages-ssl.conf
+ ```
+
+1. Edit all GitLab related configs in `/etc/nginx/site-available/` and replace
+ `0.0.0.0` with `1.1.1.1`, where `1.1.1.1` the primary IP where GitLab
+ listens to.
+1. Restart NGINX
+1. [Restart GitLab][restart]
+
+## Change storage path
+
+Follow the steps below to change the default path where GitLab Pages' contents
+are stored.
+
+1. Pages are stored by default in `/var/opt/gitlab/gitlab-rails/shared/pages`.
+ If you wish to store them in another location you must set it up in
+ `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['pages_path'] = "/mnt/storage/pages"
+ ```
+
+1. [Reconfigure GitLab][reconfigure]
+
+## NGINX caveats
+
+>**Note:**
+The following information applies only for installations from source.
+
+Be extra careful when setting up the domain name in the NGINX config. You must
+not remove the backslashes.
+
+If your GitLab pages domain is `example.io`, replace:
+
+```bash
+server_name ~^.*\.YOUR_GITLAB_PAGES\.DOMAIN$;
+```
+
+with:
+
+```
+server_name ~^.*\.example\.io$;
+```
+
+If you are using a subdomain, make sure to escape all dots (`.`) except from
+the first one with a backslash (\). For example `pages.example.io` would be:
+
+```
+server_name ~^.*\.pages\.example\.io$;
+```
+
+## Change storage path
+
+Follow the steps below to change the default path where GitLab Pages' contents
+are stored.
+
+1. Pages are stored by default in `/home/git/gitlab/shared/pages`.
+ If you wish to store them in another location you must set it up in
+ `gitlab.yml` under the `pages` section:
+
+ ```yaml
+ pages:
+ enabled: true
+ # The location where pages are stored (default: shared/pages).
+ path: /mnt/storage/pages
+ ```
+
+1. [Restart GitLab][restart]
+
+## Set maximum Pages size
+
+The maximum size of the unpacked archive per project can be configured in the
+Admin area under the Application settings in the **Maximum size of pages (MB)**.
+The default is 100MB.
+
+## Backup
+
+Pages are part of the [regular backup][backup] so there is nothing to configure.
+
+## Security
+
+You should strongly consider running GitLab pages under a different hostname
+than GitLab to prevent XSS attacks.
+
+[backup]: ../../raketasks/backup_restore.md
+[ee-80]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/80
+[ee-173]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/173
+[gitlab pages daemon]: https://gitlab.com/gitlab-org/gitlab-pages
+[NGINX configs]: https://gitlab.com/gitlab-org/gitlab-ee/tree/8-5-stable-ee/lib/support/nginx
+[pages-readme]: https://gitlab.com/gitlab-org/gitlab-pages/blob/master/README.md
+[pages-userguide]: ../../user/project/pages/index.md
+[reconfigure]: ../restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart]: ../restart_gitlab.md#installations-from-source
+[gitlab-pages]: https://gitlab.com/gitlab-org/gitlab-pages/tree/v0.4.0
+[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/init.d/gitlab.default.example
+[shared runners]: ../../ci/runners/README.md
diff --git a/doc/administration/polling.md b/doc/administration/polling.md
new file mode 100644
index 00000000000..35aaa20df2c
--- /dev/null
+++ b/doc/administration/polling.md
@@ -0,0 +1,24 @@
+# Polling configuration
+
+The GitLab UI polls for updates for different resources (issue notes, issue
+titles, pipeline statuses, etc.) on a schedule appropriate to the resource.
+
+In "Application settings -> Real-time features" you can configure "Polling
+interval multiplier". This multiplier is applied to all resources at once,
+and decimal values are supported. For the sake of the examples below, we will
+say that issue notes poll every 2 seconds, and issue titles poll every 5
+seconds; these are _not_ the actual values.
+
+- 1 is the default, and recommended for most installations. (Issue notes poll
+every 2 seconds, and issue titles poll every 5 seconds.)
+- 0 will disable UI polling completely. (On the next poll, clients will stop
+polling for updates.)
+- A value greater than 1 will slow polling down. If you see issues with
+database load from lots of clients polling for updates, increasing the
+multiplier from 1 can be a good compromise, rather than disabling polling
+completely. (For example: If this is set to 2, then issue notes poll every 4
+seconds, and issue titles poll every 10 seconds.)
+- A value between 0 and 1 will make the UI poll more frequently (so updates
+will show in other sessions faster), but is **not recommended**. 1 should be
+fast enough. (For example, if this is set to 0.5, then issue notes poll every
+1 second, and issue titles poll every 2.5 seconds.)
diff --git a/doc/administration/raketasks/check.md b/doc/administration/raketasks/check.md
new file mode 100644
index 00000000000..c8b5434c068
--- /dev/null
+++ b/doc/administration/raketasks/check.md
@@ -0,0 +1,78 @@
+# Check Rake Tasks
+
+## Repository Integrity
+
+Even though Git is very resilient and tries to prevent data integrity issues,
+there are times when things go wrong. The following Rake tasks intend to
+help GitLab administrators diagnose problem repositories so they can be fixed.
+
+There are 3 things that are checked to determine integrity.
+
+1. Git repository file system check ([git fsck](https://git-scm.com/docs/git-fsck)).
+ This step verifies the connectivity and validity of objects in the repository.
+1. Check for `config.lock` in the repository directory.
+1. Check for any branch/references lock files in `refs/heads`.
+
+It's important to note that the existence of `config.lock` or reference locks
+alone do not necessarily indicate a problem. Lock files are routinely created
+and removed as Git and GitLab perform operations on the repository. They serve
+to prevent data integrity issues. However, if a Git operation is interrupted these
+locks may not be cleaned up properly.
+
+The following symptoms may indicate a problem with repository integrity. If users
+experience these symptoms you may use the rake tasks described below to determine
+exactly which repositories are causing the trouble.
+
+- Receiving an error when trying to push code - `remote: error: cannot lock ref`
+- A 500 error when viewing the GitLab dashboard or when accessing a specific project.
+
+### Check all GitLab repositories
+
+This task loops through all repositories on the GitLab server and runs the
+3 integrity checks described previously.
+
+**Omnibus Installation**
+
+```
+sudo gitlab-rake gitlab:repo:check
+```
+
+**Source Installation**
+
+```bash
+sudo -u git -H bundle exec rake gitlab:repo:check RAILS_ENV=production
+```
+
+### Check repositories for a specific user
+
+This task checks all repositories that a specific user has access to. This is important
+because sometimes you know which user is experiencing trouble but you don't know
+which project might be the cause.
+
+If the rake task is executed without brackets at the end, you will be prompted
+to enter a username.
+
+**Omnibus Installation**
+
+```bash
+sudo gitlab-rake gitlab:user:check_repos
+sudo gitlab-rake gitlab:user:check_repos[<username>]
+```
+
+**Source Installation**
+
+```bash
+sudo -u git -H bundle exec rake gitlab:user:check_repos RAILS_ENV=production
+sudo -u git -H bundle exec rake gitlab:user:check_repos[<username>] RAILS_ENV=production
+```
+
+Example output:
+
+![gitlab:user:check_repos output](../img/raketasks/check_repos_output.png)
+
+## LDAP Check
+
+The LDAP check Rake task will test the bind_dn and password credentials
+(if configured) and will list a sample of LDAP users. This task is also
+executed as part of the `gitlab:check` task, but can run independently.
+See [LDAP Rake Tasks - LDAP Check](ldap.md#check) for details.
diff --git a/doc/administration/raketasks/github_import.md b/doc/administration/raketasks/github_import.md
new file mode 100644
index 00000000000..04c70c3644e
--- /dev/null
+++ b/doc/administration/raketasks/github_import.md
@@ -0,0 +1,36 @@
+# GitHub import
+
+>**Note:**
+>
+> - [Introduced][ce-10308] in GitLab 9.1.
+> - You need a personal access token in order to retrieve and import GitHub
+> projects. You can get it from: https://github.com/settings/tokens
+> - You also need to pass an username as the second argument to the rake task
+> which will become the owner of the project.
+
+To import a project from the list of your GitHub projects available:
+
+```bash
+# Omnibus installations
+sudo gitlab-rake import:github[access_token,root,foo/bar]
+
+# Installations from source
+bundle exec rake import:github[access_token,root,foo/bar] RAILS_ENV=production
+```
+
+In this case, `access_token` is your GitHub personal access token, `root`
+is your GitLab username, and `foo/bar` is the new GitLab namespace/project that
+will get created from your GitHub project. Subgroups are also possible: `foo/foo/bar`.
+
+
+To import a specific GitHub project (named `foo/github_repo` here):
+
+```bash
+# Omnibus installations
+sudo gitlab-rake import:github[access_token,root,foo/bar,foo/github_repo]
+
+# Installations from source
+bundle exec rake import:github[access_token,root,foo/bar,foo/github_repo] RAILS_ENV=production
+```
+
+[ce-10308]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10308
diff --git a/doc/administration/raketasks/ldap.md b/doc/administration/raketasks/ldap.md
new file mode 100644
index 00000000000..91fc0133d56
--- /dev/null
+++ b/doc/administration/raketasks/ldap.md
@@ -0,0 +1,120 @@
+# LDAP Rake Tasks
+
+## Check
+
+The LDAP check Rake task will test the `bind_dn` and `password` credentials
+(if configured) and will list a sample of LDAP users. This task is also
+executed as part of the `gitlab:check` task, but can run independently
+using the command below.
+
+**Omnibus Installation**
+
+```
+sudo gitlab-rake gitlab:ldap:check
+```
+
+**Source Installation**
+
+```bash
+sudo -u git -H bundle exec rake gitlab:ldap:check RAILS_ENV=production
+```
+
+------
+
+By default, the task will return a sample of 100 LDAP users. Change this
+limit by passing a number to the check task:
+
+```bash
+rake gitlab:ldap:check[50]
+```
+
+## Rename a provider
+
+If you change the LDAP server ID in `gitlab.yml` or `gitlab.rb` you will need
+to update all user identities or users will be unable to sign in. Input the
+old and new provider and this task will update all matching identities in the
+database.
+
+`old_provider` and `new_provider` are derived from the prefix `ldap` plus the
+LDAP server ID from the configuration file. For example, in `gitlab.yml` or
+`gitlab.rb` you may see LDAP configuration like this:
+
+```yaml
+main:
+ label: 'LDAP'
+ host: '_your_ldap_server'
+ port: 389
+ uid: 'sAMAccountName'
+ ...
+```
+
+`main` is the LDAP server ID. Together, the unique provider is `ldapmain`.
+
+> **Warning**: If you input an incorrect new provider users will be unable
+to sign in. If this happens, run the task again with the incorrect provider
+as the `old_provider` and the correct provider as the `new_provider`.
+
+**Omnibus Installation**
+
+```bash
+sudo gitlab-rake gitlab:ldap:rename_provider[old_provider,new_provider]
+```
+
+**Source Installation**
+
+```bash
+bundle exec rake gitlab:ldap:rename_provider[old_provider,new_provider] RAILS_ENV=production
+```
+
+### Example
+
+Consider beginning with the default server ID `main` (full provider `ldapmain`).
+If we change `main` to `mycompany`, the `new_provider` is `ldapmycompany`.
+To rename all user identities run the following command:
+
+```bash
+sudo gitlab-rake gitlab:ldap:rename_provider[ldapmain,ldapmycompany]
+```
+
+Example output:
+
+```
+100 users with provider 'ldapmain' will be updated to 'ldapmycompany'.
+If the new provider is incorrect, users will be unable to sign in.
+Do you want to continue (yes/no)? yes
+
+User identities were successfully updated
+```
+
+### Other options
+
+If you do not specify an `old_provider` and `new_provider` you will be prompted
+for them:
+
+**Omnibus Installation**
+
+```bash
+sudo gitlab-rake gitlab:ldap:rename_provider
+```
+
+**Source Installation**
+
+```bash
+bundle exec rake gitlab:ldap:rename_provider RAILS_ENV=production
+```
+
+**Example output:**
+
+```
+What is the old provider? Ex. 'ldapmain': ldapmain
+What is the new provider? Ex. 'ldapcustom': ldapmycompany
+```
+
+------
+
+This tasks also accepts the `force` environment variable which will skip the
+confirmation dialog:
+
+```bash
+sudo gitlab-rake gitlab:ldap:rename_provider[old_provider,new_provider] force=yes
+```
diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md
new file mode 100644
index 00000000000..5b6ee354887
--- /dev/null
+++ b/doc/administration/raketasks/maintenance.md
@@ -0,0 +1,221 @@
+# Maintenance Rake Tasks
+
+## Gather information about GitLab and the system it runs on
+
+This command gathers information about your GitLab installation and the System it runs on. These may be useful when asking for help or reporting issues.
+
+**Omnibus Installation**
+
+```
+sudo gitlab-rake gitlab:env:info
+```
+
+**Source Installation**
+
+```
+bundle exec rake gitlab:env:info RAILS_ENV=production
+```
+
+Example output:
+
+```
+System information
+System: Debian 7.8
+Current User: git
+Using RVM: no
+Ruby Version: 2.1.5p273
+Gem Version: 2.4.3
+Bundler Version: 1.7.6
+Rake Version: 10.3.2
+Redis Version: 3.2.5
+Sidekiq Version: 2.17.8
+
+GitLab information
+Version: 7.7.1
+Revision: 41ab9e1
+Directory: /home/git/gitlab
+DB Adapter: postgresql
+URL: https://gitlab.example.com
+HTTP Clone URL: https://gitlab.example.com/some-project.git
+SSH Clone URL: git@gitlab.example.com:some-project.git
+Using LDAP: no
+Using Omniauth: no
+
+GitLab Shell
+Version: 2.4.1
+Repositories: /home/git/repositories/
+Hooks: /home/git/gitlab-shell/hooks/
+Git: /usr/bin/git
+```
+
+## Check GitLab configuration
+
+Runs the following rake tasks:
+
+- `gitlab:gitlab_shell:check`
+- `gitlab:sidekiq:check`
+- `gitlab:app:check`
+
+It will check that each component was setup according to the installation guide and suggest fixes for issues found.
+
+You may also have a look at our [Trouble Shooting Guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide).
+
+**Omnibus Installation**
+
+```
+sudo gitlab-rake gitlab:check
+```
+
+**Source Installation**
+
+```
+bundle exec rake gitlab:check RAILS_ENV=production
+```
+
+NOTE: Use SANITIZE=true for gitlab:check if you want to omit project names from the output.
+
+Example output:
+
+```
+Checking Environment ...
+
+Git configured for git user? ... yes
+Has python2? ... yes
+python2 is supported version? ... yes
+
+Checking Environment ... Finished
+
+Checking GitLab Shell ...
+
+GitLab Shell version? ... OK (1.2.0)
+Repo base directory exists? ... yes
+Repo base directory is a symlink? ... no
+Repo base owned by git:git? ... yes
+Repo base access is drwxrws---? ... yes
+post-receive hook up-to-date? ... yes
+post-receive hooks in repos are links: ... yes
+
+Checking GitLab Shell ... Finished
+
+Checking Sidekiq ...
+
+Running? ... yes
+
+Checking Sidekiq ... Finished
+
+Checking GitLab ...
+
+Database config exists? ... yes
+Database is SQLite ... no
+All migrations up? ... yes
+GitLab config exists? ... yes
+GitLab config outdated? ... no
+Log directory writable? ... yes
+Tmp directory writable? ... yes
+Init script exists? ... yes
+Init script up-to-date? ... yes
+Redis version >= 2.0.0? ... yes
+
+Checking GitLab ... Finished
+```
+
+## Rebuild authorized_keys file
+
+In some case it is necessary to rebuild the `authorized_keys` file.
+
+**Omnibus Installation**
+
+```
+sudo gitlab-rake gitlab:shell:setup
+```
+
+**Source Installation**
+
+```
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:shell:setup RAILS_ENV=production
+```
+
+```
+This will rebuild an authorized_keys file.
+You will lose any data stored in authorized_keys file.
+Do you want to continue (yes/no)? yes
+```
+
+## Clear redis cache
+
+If for some reason the dashboard shows wrong information you might want to
+clear Redis' cache.
+
+**Omnibus Installation**
+
+```
+sudo gitlab-rake cache:clear
+```
+
+**Source Installation**
+
+```
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
+```
+
+## Precompile the assets
+
+Sometimes during version upgrades you might end up with some wrong CSS or
+missing some icons. In that case, try to precompile the assets again.
+
+Note that this only applies to source installations and does NOT apply to
+Omnibus packages.
+
+**Source Installation**
+
+```
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production
+```
+
+For omnibus versions, the unoptimized assets (JavaScript, CSS) are frozen at
+the release of upstream GitLab. The omnibus version includes optimized versions
+of those assets. Unless you are modifying the JavaScript / CSS code on your
+production machine after installing the package, there should be no reason to redo
+rake gitlab:assets:compile on the production machine. If you suspect that assets
+have been corrupted, you should reinstall the omnibus package.
+
+## Tracking Deployments
+
+GitLab provides a Rake task that lets you track deployments in GitLab
+Performance Monitoring. This Rake task simply stores the current GitLab version
+in the GitLab Performance Monitoring database.
+
+**Omnibus Installation**
+
+```
+sudo gitlab-rake gitlab:track_deployment
+```
+
+**Source Installation**
+
+```
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:track_deployment RAILS_ENV=production
+```
+
+## Create or repair repository hooks symlink
+
+If the GitLab shell hooks directory location changes or another circumstance
+leads to the hooks symlink becoming missing or invalid, run this Rake task
+to create or repair the symlinks.
+
+**Omnibus Installation**
+
+```
+sudo gitlab-rake gitlab:shell:create_hooks
+```
+
+**Source Installation**
+
+```
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:shell:create_hooks RAILS_ENV=production
+```
diff --git a/doc/administration/reply_by_email.md b/doc/administration/reply_by_email.md
new file mode 100644
index 00000000000..e99a7ee29cc
--- /dev/null
+++ b/doc/administration/reply_by_email.md
@@ -0,0 +1,364 @@
+# Reply by email
+
+GitLab can be set up to allow users to comment on issues and merge requests by
+replying to notification emails.
+
+## Requirement
+
+Reply by email requires an IMAP-enabled email account. GitLab allows you to use
+three strategies for this feature:
+- using email sub-addressing
+- using a dedicated email address
+- using a catch-all mailbox
+
+### Email sub-addressing
+
+**If your provider or server supports email sub-addressing, we recommend using it.
+Some features (e.g. create new issue via email) only work with sub-addressing.**
+
+[Sub-addressing](https://en.wikipedia.org/wiki/Email_address#Sub-addressing) is
+a feature where any email to `user+some_arbitrary_tag@example.com` will end up
+in the mailbox for `user@example.com`, and is supported by providers such as
+Gmail, Google Apps, Yahoo! Mail, Outlook.com and iCloud, as well as the Postfix
+mail server which you can run on-premises.
+
+### Dedicated email address
+
+This solution is really simple to set up: you just have to create an email
+address dedicated to receive your users' replies to GitLab notifications.
+
+### Catch-all mailbox
+
+A [catch-all mailbox](https://en.wikipedia.org/wiki/Catch-all) for a domain will
+"catch all" the emails addressed to the domain that do not exist in the mail
+server.
+
+## How it works?
+
+### 1. GitLab sends a notification email
+
+When GitLab sends a notification and Reply by email is enabled, the `Reply-To`
+header is set to the address defined in your GitLab configuration, with the
+`%{key}` placeholder (if present) replaced by a specific "reply key". In
+addition, this "reply key" is also added to the `References` header.
+
+### 2. You reply to the notification email
+
+When you reply to the notification email, your email client will:
+
+- send the email to the `Reply-To` address it got from the notification email
+- set the `In-Reply-To` header to the value of the `Message-ID` header from the
+ notification email
+- set the `References` header to the value of the `Message-ID` plus the value of
+ the notification email's `References` header.
+
+### 3. GitLab receives your reply to the notification email
+
+When GitLab receives your reply, it will look for the "reply key" in the
+following headers, in this order:
+
+1. the `To` header
+1. the `References` header
+
+If it finds a reply key, it will be able to leave your reply as a comment on
+the entity the notification was about (issue, merge request, commit...).
+
+For more details about the `Message-ID`, `In-Reply-To`, and `References headers`,
+please consult [RFC 5322](https://tools.ietf.org/html/rfc5322#section-3.6.4).
+
+## Set it up
+
+If you want to use Gmail / Google Apps with Reply by email, make sure you have
+[IMAP access enabled](https://support.google.com/mail/troubleshooter/1668960?hl=en#ts=1665018)
+and [allowed less secure apps to access the account](https://support.google.com/accounts/answer/6010255)
+or [turn-on 2-step validation](https://support.google.com/accounts/answer/185839)
+and use [an application password](https://support.google.com/mail/answer/185833).
+
+To set up a basic Postfix mail server with IMAP access on Ubuntu, follow the
+[Postfix setup documentation](reply_by_email_postfix_setup.md).
+
+### Omnibus package installations
+
+1. Find the `incoming_email` section in `/etc/gitlab/gitlab.rb`, enable the
+ feature and fill in the details for your specific IMAP server and email account:
+
+ ```ruby
+ # Configuration for Postfix mail server, assumes mailbox incoming@gitlab.example.com
+ gitlab_rails['incoming_email_enabled'] = true
+
+ # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
+ # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
+ gitlab_rails['incoming_email_address'] = "incoming+%{key}@gitlab.example.com"
+
+ # Email account username
+ # With third party providers, this is usually the full email address.
+ # With self-hosted email servers, this is usually the user part of the email address.
+ gitlab_rails['incoming_email_email'] = "incoming"
+ # Email account password
+ gitlab_rails['incoming_email_password'] = "[REDACTED]"
+
+ # IMAP server host
+ gitlab_rails['incoming_email_host'] = "gitlab.example.com"
+ # IMAP server port
+ gitlab_rails['incoming_email_port'] = 143
+ # Whether the IMAP server uses SSL
+ gitlab_rails['incoming_email_ssl'] = false
+ # Whether the IMAP server uses StartTLS
+ gitlab_rails['incoming_email_start_tls'] = false
+
+ # The mailbox where incoming mail will end up. Usually "inbox".
+ gitlab_rails['incoming_email_mailbox_name'] = "inbox"
+ # The IDLE command timeout.
+ gitlab_rails['incoming_email_idle_timeout'] = 60
+ ```
+
+ ```ruby
+ # Configuration for Gmail / Google Apps, assumes mailbox gitlab-incoming@gmail.com
+ gitlab_rails['incoming_email_enabled'] = true
+
+ # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
+ # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
+ gitlab_rails['incoming_email_address'] = "gitlab-incoming+%{key}@gmail.com"
+
+ # Email account username
+ # With third party providers, this is usually the full email address.
+ # With self-hosted email servers, this is usually the user part of the email address.
+ gitlab_rails['incoming_email_email'] = "gitlab-incoming@gmail.com"
+ # Email account password
+ gitlab_rails['incoming_email_password'] = "[REDACTED]"
+
+ # IMAP server host
+ gitlab_rails['incoming_email_host'] = "imap.gmail.com"
+ # IMAP server port
+ gitlab_rails['incoming_email_port'] = 993
+ # Whether the IMAP server uses SSL
+ gitlab_rails['incoming_email_ssl'] = true
+ # Whether the IMAP server uses StartTLS
+ gitlab_rails['incoming_email_start_tls'] = false
+
+ # The mailbox where incoming mail will end up. Usually "inbox".
+ gitlab_rails['incoming_email_mailbox_name'] = "inbox"
+ # The IDLE command timeout.
+ gitlab_rails['incoming_email_idle_timeout'] = 60
+ ```
+
+ ```ruby
+ # Configuration for Microsoft Exchange mail server w/ IMAP enabled, assumes mailbox incoming@exchange.example.com
+ gitlab_rails['incoming_email_enabled'] = true
+
+ # The email address replies are sent to - Exchange does not support sub-addressing so %{key} is not used here
+ gitlab_rails['incoming_email_address'] = "incoming@exchange.example.com"
+
+ # Email account username
+ # Typically this is the userPrincipalName (UPN)
+ gitlab_rails['incoming_email_email'] = "incoming@ad-domain.example.com"
+ # Email account password
+ gitlab_rails['incoming_email_password'] = "[REDACTED]"
+
+ # IMAP server host
+ gitlab_rails['incoming_email_host'] = "exchange.example.com"
+ # IMAP server port
+ gitlab_rails['incoming_email_port'] = 993
+ # Whether the IMAP server uses SSL
+ gitlab_rails['incoming_email_ssl'] = true
+ ```
+
+1. Reconfigure GitLab for the changes to take effect:
+
+ ```sh
+ sudo gitlab-ctl reconfigure
+ ```
+
+1. Verify that everything is configured correctly:
+
+ ```sh
+ sudo gitlab-rake gitlab:incoming_email:check
+ ```
+
+1. Reply by email should now be working.
+
+### Installations from source
+
+1. Go to the GitLab installation directory:
+
+ ```sh
+ cd /home/git/gitlab
+ ```
+
+1. Find the `incoming_email` section in `config/gitlab.yml`, enable the feature
+ and fill in the details for your specific IMAP server and email account:
+
+ ```sh
+ sudo editor config/gitlab.yml
+ ```
+
+ ```yaml
+ # Configuration for Postfix mail server, assumes mailbox incoming@gitlab.example.com
+ incoming_email:
+ enabled: true
+
+ # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
+ # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
+ address: "incoming+%{key}@gitlab.example.com"
+
+ # Email account username
+ # With third party providers, this is usually the full email address.
+ # With self-hosted email servers, this is usually the user part of the email address.
+ user: "incoming"
+ # Email account password
+ password: "[REDACTED]"
+
+ # IMAP server host
+ host: "gitlab.example.com"
+ # IMAP server port
+ port: 143
+ # Whether the IMAP server uses SSL
+ ssl: false
+ # Whether the IMAP server uses StartTLS
+ start_tls: false
+
+ # The mailbox where incoming mail will end up. Usually "inbox".
+ mailbox: "inbox"
+ # The IDLE command timeout.
+ idle_timeout: 60
+ ```
+
+ ```yaml
+ # Configuration for Gmail / Google Apps, assumes mailbox gitlab-incoming@gmail.com
+ incoming_email:
+ enabled: true
+
+ # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
+ # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
+ address: "gitlab-incoming+%{key}@gmail.com"
+
+ # Email account username
+ # With third party providers, this is usually the full email address.
+ # With self-hosted email servers, this is usually the user part of the email address.
+ user: "gitlab-incoming@gmail.com"
+ # Email account password
+ password: "[REDACTED]"
+
+ # IMAP server host
+ host: "imap.gmail.com"
+ # IMAP server port
+ port: 993
+ # Whether the IMAP server uses SSL
+ ssl: true
+ # Whether the IMAP server uses StartTLS
+ start_tls: false
+
+ # The mailbox where incoming mail will end up. Usually "inbox".
+ mailbox: "inbox"
+ # The IDLE command timeout.
+ idle_timeout: 60
+ ```
+
+ ```yaml
+ # Configuration for Microsoft Exchange mail server w/ IMAP enabled, assumes mailbox incoming@exchange.example.com
+ incoming_email:
+ enabled: true
+
+ # The email address replies are sent to - Exchange does not support sub-addressing so %{key} is not used here
+ address: "incoming@exchange.example.com"
+
+ # Email account username
+ # Typically this is the userPrincipalName (UPN)
+ user: "incoming@ad-domain.example.com"
+ # Email account password
+ password: "[REDACTED]"
+
+ # IMAP server host
+ host: "exchange.example.com"
+ # IMAP server port
+ port: 993
+ # Whether the IMAP server uses SSL
+ ssl: true
+ # Whether the IMAP server uses StartTLS
+ start_tls: false
+
+ # The mailbox where incoming mail will end up. Usually "inbox".
+ mailbox: "inbox"
+ # The IDLE command timeout.
+ idle_timeout: 60
+ ```
+
+1. Enable `mail_room` in the init script at `/etc/default/gitlab`:
+
+ ```sh
+ sudo mkdir -p /etc/default
+ echo 'mail_room_enabled=true' | sudo tee -a /etc/default/gitlab
+ ```
+
+1. Restart GitLab:
+
+ ```sh
+ sudo service gitlab restart
+ ```
+
+1. Verify that everything is configured correctly:
+
+ ```sh
+ sudo -u git -H bundle exec rake gitlab:incoming_email:check RAILS_ENV=production
+ ```
+
+1. Reply by email should now be working.
+
+### Development
+
+1. Go to the GitLab installation directory.
+
+1. Find the `incoming_email` section in `config/gitlab.yml`, enable the feature and fill in the details for your specific IMAP server and email account:
+
+ ```yaml
+ # Configuration for Gmail / Google Apps, assumes mailbox gitlab-incoming@gmail.com
+ incoming_email:
+ enabled: true
+
+ # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
+ # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
+ address: "gitlab-incoming+%{key}@gmail.com"
+
+ # Email account username
+ # With third party providers, this is usually the full email address.
+ # With self-hosted email servers, this is usually the user part of the email address.
+ user: "gitlab-incoming@gmail.com"
+ # Email account password
+ password: "[REDACTED]"
+
+ # IMAP server host
+ host: "imap.gmail.com"
+ # IMAP server port
+ port: 993
+ # Whether the IMAP server uses SSL
+ ssl: true
+ # Whether the IMAP server uses StartTLS
+ start_tls: false
+
+ # The mailbox where incoming mail will end up. Usually "inbox".
+ mailbox: "inbox"
+ # The IDLE command timeout.
+ idle_timeout: 60
+ ```
+
+ As mentioned, the part after `+` is ignored, and this will end up in the mailbox for `gitlab-incoming@gmail.com`.
+
+1. Uncomment the `mail_room` line in your `Procfile`:
+
+ ```yaml
+ mail_room: bundle exec mail_room -q -c config/mail_room.yml
+ ```
+
+1. Restart GitLab:
+
+ ```sh
+ bundle exec foreman start
+ ```
+
+1. Verify that everything is configured correctly:
+
+ ```sh
+ bundle exec rake gitlab:incoming_email:check RAILS_ENV=development
+ ```
+
+1. Reply by email should now be working.
diff --git a/doc/administration/reply_by_email_postfix_setup.md b/doc/administration/reply_by_email_postfix_setup.md
new file mode 100644
index 00000000000..3b8c716eff5
--- /dev/null
+++ b/doc/administration/reply_by_email_postfix_setup.md
@@ -0,0 +1,324 @@
+# Set up Postfix for Reply by email
+
+This document will take you through the steps of setting up a basic Postfix mail
+server with IMAP authentication on Ubuntu, to be used with [Reply by email].
+
+The instructions make the assumption that you will be using the email address `incoming@gitlab.example.com`, that is, username `incoming` on host `gitlab.example.com`. Don't forget to change it to your actual host when executing the example code snippets.
+
+## Configure your server firewall
+
+1. Open up port 25 on your server so that people can send email into the server over SMTP.
+2. If the mail server is different from the server running GitLab, open up port 143 on your server so that GitLab can read email from the server over IMAP.
+
+## Install packages
+
+1. Install the `postfix` package if it is not installed already:
+
+ ```sh
+ sudo apt-get install postfix
+ ```
+
+ When asked about the environment, select 'Internet Site'. When asked to confirm the hostname, make sure it matches `gitlab.example.com`.
+
+1. Install the `mailutils` package.
+
+ ```sh
+ sudo apt-get install mailutils
+ ```
+
+## Create user
+
+1. Create a user for incoming email.
+
+ ```sh
+ sudo useradd -m -s /bin/bash incoming
+ ```
+
+1. Set a password for this user.
+
+ ```sh
+ sudo passwd incoming
+ ```
+
+ Be sure not to forget this, you'll need it later.
+
+## Test the out-of-the-box setup
+
+1. Connect to the local SMTP server:
+
+ ```sh
+ telnet localhost 25
+ ```
+
+ You should see a prompt like this:
+
+ ```sh
+ Trying 127.0.0.1...
+ Connected to localhost.
+ Escape character is '^]'.
+ 220 gitlab.example.com ESMTP Postfix (Ubuntu)
+ ```
+
+ If you get a `Connection refused` error instead, verify that `postfix` is running:
+
+ ```sh
+ sudo postfix status
+ ```
+
+ If it is not, start it:
+
+ ```sh
+ sudo postfix start
+ ```
+
+1. Send the new `incoming` user a dummy email to test SMTP, by entering the following into the SMTP prompt:
+
+ ```
+ ehlo localhost
+ mail from: root@localhost
+ rcpt to: incoming@localhost
+ data
+ Subject: Re: Some issue
+
+ Sounds good!
+ .
+ quit
+ ```
+
+ _**Note:** The `.` is a literal period on its own line._
+
+ _**Note:** If you receive an error after entering `rcpt to: incoming@localhost`
+ then your Postfix `my_network` configuration is not correct. The error will
+ say 'Temporary lookup failure'. See
+ [Configure Postfix to receive email from the Internet](#configure-postfix-to-receive-email-from-the-internet)._
+
+1. Check if the `incoming` user received the email:
+
+ ```sh
+ su - incoming
+ mail
+ ```
+
+ You should see output like this:
+
+ ```
+ "/var/mail/incoming": 1 message 1 unread
+ >U 1 root@localhost 59/2842 Re: Some issue
+ ```
+
+ Quit the mail app:
+
+ ```sh
+ q
+ ```
+
+1. Log out of the `incoming` account and go back to being `root`:
+
+ ```sh
+ logout
+ ```
+
+## Configure Postfix to use Maildir-style mailboxes
+
+Courier, which we will install later to add IMAP authentication, requires mailboxes to have the Maildir format, rather than mbox.
+
+1. Configure Postfix to use Maildir-style mailboxes:
+
+ ```sh
+ sudo postconf -e "home_mailbox = Maildir/"
+ ```
+
+1. Restart Postfix:
+
+ ```sh
+ sudo /etc/init.d/postfix restart
+ ```
+
+1. Test the new setup:
+
+ 1. Follow steps 1 and 2 of _[Test the out-of-the-box setup](#test-the-out-of-the-box-setup)_.
+ 1. Check if the `incoming` user received the email:
+
+ ```sh
+ su - incoming
+ MAIL=/home/incoming/Maildir
+ mail
+ ```
+
+ You should see output like this:
+
+ ```
+ "/home/incoming/Maildir": 1 message 1 unread
+ >U 1 root@localhost 59/2842 Re: Some issue
+ ```
+
+ Quit the mail app:
+
+ ```sh
+ q
+ ```
+
+ _**Note:** If `mail` returns an error `Maildir: Is a directory` then your
+ version of `mail` doesn't support Maildir style mailboxes. Install
+ `heirloom-mailx` by running `sudo apt-get install heirloom-mailx`. Then,
+ try the above steps again, substituting `heirloom-mailx` for the `mail`
+ command._
+
+1. Log out of the `incoming` account and go back to being `root`:
+
+ ```sh
+ logout
+ ```
+
+## Install the Courier IMAP server
+
+1. Install the `courier-imap` package:
+
+ ```sh
+ sudo apt-get install courier-imap
+ ```
+
+## Configure Postfix to receive email from the internet
+
+1. Let Postfix know about the domains that it should consider local:
+
+ ```sh
+ sudo postconf -e "mydestination = gitlab.example.com, localhost.localdomain, localhost"
+ ```
+
+1. Let Postfix know about the IPs that it should consider part of the LAN:
+
+ We'll assume `192.168.1.0/24` is your local LAN. You can safely skip this step if you don't have other machines in the same local network.
+
+ ```sh
+ sudo postconf -e "mynetworks = 127.0.0.0/8, 192.168.1.0/24"
+ ```
+
+1. Configure Postfix to receive mail on all interfaces, which includes the internet:
+
+ ```sh
+ sudo postconf -e "inet_interfaces = all"
+ ```
+
+1. Configure Postfix to use the `+` delimiter for sub-addressing:
+
+ ```sh
+ sudo postconf -e "recipient_delimiter = +"
+ ```
+
+1. Restart Postfix:
+
+ ```sh
+ sudo service postfix restart
+ ```
+
+## Test the final setup
+
+1. Test SMTP under the new setup:
+
+ 1. Connect to the SMTP server:
+
+ ```sh
+ telnet gitlab.example.com 25
+ ```
+
+ You should see a prompt like this:
+
+ ```sh
+ Trying 123.123.123.123...
+ Connected to gitlab.example.com.
+ Escape character is '^]'.
+ 220 gitlab.example.com ESMTP Postfix (Ubuntu)
+ ```
+
+ If you get a `Connection refused` error instead, make sure your firewall is setup to allow inbound traffic on port 25.
+
+ 1. Send the `incoming` user a dummy email to test SMTP, by entering the following into the SMTP prompt:
+
+ ```
+ ehlo gitlab.example.com
+ mail from: root@gitlab.example.com
+ rcpt to: incoming@gitlab.example.com
+ data
+ Subject: Re: Some issue
+
+ Sounds good!
+ .
+ quit
+ ```
+
+ (Note: The `.` is a literal period on its own line)
+
+ 1. Check if the `incoming` user received the email:
+
+ ```sh
+ su - incoming
+ MAIL=/home/incoming/Maildir
+ mail
+ ```
+
+ You should see output like this:
+
+ ```
+ "/home/incoming/Maildir": 1 message 1 unread
+ >U 1 root@gitlab.example.com 59/2842 Re: Some issue
+ ```
+
+ Quit the mail app:
+
+ ```sh
+ q
+ ```
+
+ 1. Log out of the `incoming` account and go back to being `root`:
+
+ ```sh
+ logout
+ ```
+
+1. Test IMAP under the new setup:
+
+ 1. Connect to the IMAP server:
+
+ ```sh
+ telnet gitlab.example.com 143
+ ```
+
+ You should see a prompt like this:
+
+ ```sh
+ Trying 123.123.123.123...
+ Connected to mail.example.gitlab.com.
+ Escape character is '^]'.
+ - OK [CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE ACL ACL2=UNION] Courier-IMAP ready. Copyright 1998-2011 Double Precision, Inc. See COPYING for distribution information.
+ ```
+
+ 1. Sign in as the `incoming` user to test IMAP, by entering the following into the IMAP prompt:
+
+ ```
+ a login incoming PASSWORD
+ ```
+
+ Replace PASSWORD with the password you set on the `incoming` user earlier.
+
+ You should see output like this:
+
+ ```
+ a OK LOGIN Ok.
+ ```
+
+ 1. Disconnect from the IMAP server:
+
+ ```sh
+ a logout
+ ```
+
+## Done!
+
+If all the tests were successful, Postfix is all set up and ready to receive email! Continue with the [Reply by email](./reply_by_email.md) guide to configure GitLab.
+
+---
+
+_This document was adapted from https://help.ubuntu.com/community/PostfixBasicSetupHowto, by contributors to the Ubuntu documentation wiki._
+
+[reply by email]: reply_by_email.md
diff --git a/doc/administration/repository_checks.md b/doc/administration/repository_checks.md
index bc2b1f20ed3..ee37ea49874 100644
--- a/doc/administration/repository_checks.md
+++ b/doc/administration/repository_checks.md
@@ -13,12 +13,12 @@ checks failed you can see their output on the admin log page under
## Periodic checks
-GitLab periodically runs a repository check on all project repositories and
-wiki repositories in order to detect data corruption problems. A
-project will be checked no more than once per week. If any projects
+When enabled, GitLab periodically runs a repository check on all project
+repositories and wiki repositories in order to detect data corruption problems.
+A project will be checked no more than once per month. If any projects
fail their repository checks all GitLab administrators will receive an email
-notification of the situation. This notification is sent out no more
-than once a day.
+notification of the situation. This notification is sent out once a week on
+Sunday, by default.
## Disabling periodic checks
diff --git a/doc/administration/repository_storage_paths.md b/doc/administration/repository_storage_paths.md
new file mode 100644
index 00000000000..55a45119525
--- /dev/null
+++ b/doc/administration/repository_storage_paths.md
@@ -0,0 +1,105 @@
+# Repository storage paths
+
+> [Introduced][ce-4578] in GitLab 8.10.
+
+GitLab allows you to define multiple repository storage paths to distribute the
+storage load between several mount points.
+
+>**Notes:**
+>
+- You must have at least one storage path called `default`.
+- The paths are defined in key-value pairs. The key is an arbitrary name you
+ can pick to name the file path.
+- The target directories and any of its subpaths must not be a symlink.
+
+## Configure GitLab
+
+>**Warning:**
+In order for [backups] to work correctly, the storage path must **not** be a
+mount point and the GitLab user should have correct permissions for the parent
+directory of the path. In Omnibus GitLab this is taken care of automatically,
+but for source installations you should be extra careful.
+>
+The thing is that for compatibility reasons `gitlab.yml` has a different
+structure than Omnibus. In `gitlab.yml` you indicate the path for the
+repositories, for example `/home/git/repositories`, while in Omnibus you
+indicate `git_data_dirs`, which for the example above would be `/home/git`.
+Then, Omnibus will create a `repositories` directory under that path to use with
+`gitlab.yml`.
+>
+This little detail matters because while restoring a backup, the current
+contents of `/home/git/repositories` [are moved to][raketask] `/home/git/repositories.old`,
+so if `/home/git/repositories` is the mount point, then `mv` would be moving
+things between mount points, and bad things could happen. Ideally,
+`/home/git` would be the mount point, so then things would be moving within the
+same mount point. This is guaranteed with Omnibus installations (because they
+don't specify the full repository path but the parent path), but not for source
+installations.
+
+---
+
+Now that you've read that big fat warning above, let's edit the configuration
+files and add the full paths of the alternative repository storage paths. In
+the example below, we add two more mountpoints that are named `nfs` and `cephfs`
+respectively.
+
+**For installations from source**
+
+1. Edit `gitlab.yml` and add the storage paths:
+
+ ```yaml
+ repositories:
+ # Paths where repositories can be stored. Give the canonicalized absolute pathname.
+ # NOTE: REPOS PATHS MUST NOT CONTAIN ANY SYMLINK!!!
+ storages: # You must have at least a 'default' storage path.
+ default:
+ path: /home/git/repositories
+ nfs:
+ path: /mnt/nfs/repositories
+ cephfs:
+ path: /mnt/cephfs/repositories
+ ```
+
+1. [Restart GitLab] for the changes to take effect.
+
+>**Note:**
+The [`gitlab_shell: repos_path` entry][repospath] in `gitlab.yml` will be
+deprecated and replaced by `repositories: storages` in the future, so if you
+are upgrading from a version prior to 8.10, make sure to add the configuration
+as described in the step above. After you make the changes and confirm they are
+working, you can remove the `repos_path` line.
+
+---
+
+**For Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` by appending the rest of the paths to the
+ default one:
+
+ ```ruby
+ git_data_dirs({
+ "default" => { "path" => "/var/opt/gitlab/git-data" },
+ "nfs" => { "path" => "/mnt/nfs/git-data" },
+ "cephfs" => { "path" => "/mnt/cephfs/git-data" }
+ })
+ ```
+
+ Note that Omnibus stores the repositories in a `repositories` subdirectory
+ of the `git-data` directory.
+
+## Choose where new project repositories will be stored
+
+Once you set the multiple storage paths, you can choose where new projects will
+be stored via the **Application Settings** in the Admin area.
+
+![Choose repository storage path in Admin area](img/repository_storages_admin_ui.png)
+
+Beginning with GitLab 8.13.4, multiple paths can be chosen. New projects will be
+randomly placed on one of the selected paths.
+
+[ce-4578]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4578
+[restart gitlab]: restart_gitlab.md#installations-from-source
+[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure
+[backups]: ../raketasks/backup_restore.md
+[raketask]: https://gitlab.com/gitlab-org/gitlab-ce/blob/033e5423a2594e08a7ebcd2379bd2331f4c39032/lib/backup/repository.rb#L54-56
+[repospath]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-9-stable/config/gitlab.yml.example#L457
diff --git a/doc/administration/repository_storages.md b/doc/administration/repository_storages.md
index 55b054fc1a4..9d41ba77f34 100644
--- a/doc/administration/repository_storages.md
+++ b/doc/administration/repository_storages.md
@@ -1,99 +1,3 @@
# Repository storages
-> [Introduced][ce-4578] in GitLab 8.10.
-
-GitLab allows you to define multiple repository storage paths to distribute the
-storage load between several mount points.
-
->**Notes:**
->
-- You must have at least one storage path called `default`.
-- The paths are defined in key-value pairs. The key is an arbitrary name you
- can pick to name the file path.
-- The target directories and any of its subpaths must not be a symlink.
-
-## Configure GitLab
-
->**Warning:**
-In order for [backups] to work correctly, the storage path must **not** be a
-mount point and the GitLab user should have correct permissions for the parent
-directory of the path. In Omnibus GitLab this is taken care of automatically,
-but for source installations you should be extra careful.
->
-The thing is that for compatibility reasons `gitlab.yml` has a different
-structure than Omnibus. In `gitlab.yml` you indicate the path for the
-repositories, for example `/home/git/repositories`, while in Omnibus you
-indicate `git_data_dirs`, which for the example above would be `/home/git`.
-Then, Omnibus will create a `repositories` directory under that path to use with
-`gitlab.yml`.
->
-This little detail matters because while restoring a backup, the current
-contents of `/home/git/repositories` [are moved to][raketask] `/home/git/repositories.old`,
-so if `/home/git/repositories` is the mount point, then `mv` would be moving
-things between mount points, and bad things could happen. Ideally,
-`/home/git` would be the mount point, so then things would be moving within the
-same mount point. This is guaranteed with Omnibus installations (because they
-don't specify the full repository path but the parent path), but not for source
-installations.
-
----
-
-Now that you've read that big fat warning above, let's edit the configuration
-files and add the full paths of the alternative repository storage paths. In
-the example below, we add two more mountpoints that are named `nfs` and `cephfs`
-respectively.
-
-**For installations from source**
-
-1. Edit `gitlab.yml` and add the storage paths:
-
- ```yaml
- repositories:
- # Paths where repositories can be stored. Give the canonicalized absolute pathname.
- # NOTE: REPOS PATHS MUST NOT CONTAIN ANY SYMLINK!!!
- storages: # You must have at least a 'default' storage path.
- default: /home/git/repositories
- nfs: /mnt/nfs/repositories
- cephfs: /mnt/cephfs/repositories
- ```
-
-1. [Restart GitLab] for the changes to take effect.
-
->**Note:**
-The [`gitlab_shell: repos_path` entry][repospath] in `gitlab.yml` will be
-deprecated and replaced by `repositories: storages` in the future, so if you
-are upgrading from a version prior to 8.10, make sure to add the configuration
-as described in the step above. After you make the changes and confirm they are
-working, you can remove the `repos_path` line.
-
----
-
-**For Omnibus installations**
-
-1. Edit `/etc/gitlab/gitlab.rb` by appending the rest of the paths to the
- default one:
-
- ```ruby
- git_data_dirs({
- "default" => "/var/opt/gitlab/git-data",
- "nfs" => "/mnt/nfs/git-data",
- "cephfs" => "/mnt/cephfs/git-data"
- })
- ```
-
- Note that Omnibus stores the repositories in a `repositories` subdirectory
- of the `git-data` directory.
-
-## Choose where new project repositories will be stored
-
-Once you set the multiple storage paths, you can choose where new projects will
-be stored via the **Application Settings** in the Admin area.
-
-![Choose repository storage path in Admin area](img/repository_storages_admin_ui.png)
-
-[ce-4578]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4578
-[restart gitlab]: restart_gitlab.md#installations-from-source
-[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure
-[backups]: ../raketasks/backup_restore.md
-[raketask]: https://gitlab.com/gitlab-org/gitlab-ce/blob/033e5423a2594e08a7ebcd2379bd2331f4c39032/lib/backup/repository.rb#L54-56
-[repospath]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-9-stable/config/gitlab.yml.example#L457
+This document was moved to a [new location](repository_storage_paths.md).
diff --git a/doc/administration/restart_gitlab.md b/doc/administration/restart_gitlab.md
index 483060395dd..b561c2f82aa 100644
--- a/doc/administration/restart_gitlab.md
+++ b/doc/administration/restart_gitlab.md
@@ -139,7 +139,7 @@ If you are using other init systems, like systemd, you can check the
[omnibus-dl]: https://about.gitlab.com/downloads/ "Download the Omnibus packages"
[install]: ../install/installation.md "Documentation to install GitLab from source"
-[mailroom]: ../incoming_email/README.md "Used for replying by email in GitLab issues and merge requests"
+[mailroom]: reply_by_email.md "Used for replying by email in GitLab issues and merge requests"
[chef]: https://www.chef.io/chef/ "Chef official website"
[src-service]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/init.d/gitlab "GitLab init service file"
[gl-recipes]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/init "GitLab Recipes repository"
diff --git a/doc/administration/troubleshooting/debug.md b/doc/administration/troubleshooting/debug.md
index d127d7b85e5..6f1356ddf8f 100644
--- a/doc/administration/troubleshooting/debug.md
+++ b/doc/administration/troubleshooting/debug.md
@@ -107,7 +107,7 @@ downtime. Otherwise skip to the next section.
1. To see the current threads, run:
```
- apply all thread bt
+ thread apply all bt
```
1. Once you're done debugging with `gdb`, be sure to detach from the process and exit:
@@ -144,14 +144,14 @@ separate Rails process to debug the issue:
1. Obtain the private token for your user (Profile Settings -> Account).
1. Bring up the GitLab Rails console. For omnibus users, run:
- ````
+ ```
sudo gitlab-rails console
```
1. At the Rails console, run:
```ruby
- [1] pry(main)> app.get '<URL FROM STEP 1>/private_token?<TOKEN FROM STEP 2>'
+ [1] pry(main)> app.get '<URL FROM STEP 2>/?private_token=<TOKEN FROM STEP 3>'
```
For example:
diff --git a/doc/api/README.md b/doc/api/README.md
index bbd5bcfb386..b7f6ee69193 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -11,25 +11,31 @@ following locations:
- [Award Emoji](award_emoji.md)
- [Branches](branches.md)
- [Broadcast Messages](broadcast_messages.md)
-- [Builds](builds.md)
-- [Build Triggers](build_triggers.md)
- [Build Variables](build_variables.md)
- [Commits](commits.md)
- [Deployments](deployments.md)
- [Deploy Keys](deploy_keys.md)
+- [Environments](environments.md)
+- [Events](events.md)
+- [Gitignores templates](templates/gitignores.md)
+- [GitLab CI Config templates](templates/gitlab_ci_ymls.md)
- [Groups](groups.md)
- [Group Access Requests](access_requests.md)
- [Group Members](members.md)
- [Issues](issues.md)
+- [Issue Boards](boards.md)
+- [Jobs](jobs.md)
- [Keys](keys.md)
- [Labels](labels.md)
- [Merge Requests](merge_requests.md)
- [Milestones](milestones.md)
-- [Open source license templates](licenses.md)
- [Namespaces](namespaces.md)
- [Notes](notes.md) (comments)
- [Notification settings](notification_settings.md)
+- [Open source license templates](templates/licenses.md)
- [Pipelines](pipelines.md)
+- [Pipeline Triggers](pipeline_triggers.md)
+- [Pipeline Schedules](pipeline_schedules.md)
- [Projects](projects.md) including setting Webhooks
- [Project Access Requests](access_requests.md)
- [Project Members](members.md)
@@ -46,19 +52,38 @@ following locations:
- [Todos](todos.md)
- [Users](users.md)
- [Validate CI configuration](ci/lint.md)
-
-### Internal CI API
+- [V3 to V4](v3_to_v4.md)
+- [Version](version.md)
The following documentation is for the [internal CI API](ci/README.md):
- [Builds](ci/builds.md)
- [Runners](ci/runners.md)
+## Road to GraphQL
+
+Going forward, we will start on moving to
+[GraphQL](http://graphql.org/learn/best-practices/) and deprecate the use of
+controller-specific endpoints. GraphQL has a number of benefits:
+
+1. We avoid having to maintain two different APIs.
+2. Callers of the API can request only what they need.
+3. It is versioned by default.
+
+It will co-exist with the current v4 REST API. If we have a v5 API, this should
+be a compatibility layer on top of GraphQL.
+
## Authentication
-All API requests require authentication via a session cookie or token. There are
-three types of tokens available: private tokens, OAuth 2 tokens, and personal
-access tokens.
+Most API requests require authentication via a session cookie or token. For
+those cases where it is not required, this will be mentioned in the documentation
+for each individual endpoint. For example, the [`/projects/:id` endpoint](projects.md).
+
+There are three types of access tokens available:
+
+1. [OAuth2 tokens](#oauth2-tokens)
+1. [Private tokens](#private-tokens)
+1. [Personal access tokens](#personal-access-tokens)
If authentication information is invalid or omitted, an error message will be
returned with status code `401`:
@@ -69,14 +94,13 @@ returned with status code `401`:
}
```
-### Private Tokens
+### Session cookie
-You need to pass a `private_token` parameter via query string or header. If passed as a
-header, the header name must be `PRIVATE-TOKEN` (uppercase and with a dash instead of
-an underscore). You can find or reset your private token in your account page
-(`/profile/account`).
+When signing in to GitLab as an ordinary user, a `_gitlab_session` cookie is
+set. The API will use this cookie for authentication if it is present, but using
+the API to generate a new session cookie is currently not supported.
-### OAuth 2 Tokens
+### OAuth2 tokens
You can use an OAuth 2 token to authenticate with the API by passing it either in the
`access_token` parameter or in the `Authorization` header.
@@ -84,81 +108,52 @@ You can use an OAuth 2 token to authenticate with the API by passing it either i
Example of using the OAuth2 token in the header:
```shell
-curl --header "Authorization: Bearer OAUTH-TOKEN" https://gitlab.example.com/api/v3/projects
+curl --header "Authorization: Bearer OAUTH-TOKEN" https://gitlab.example.com/api/v4/projects
```
Read more about [GitLab as an OAuth2 client](oauth2.md).
-### Personal Access Tokens
-
-> [Introduced][ce-3749] in GitLab 8.8.
-
-You can create as many personal access tokens as you like from your GitLab
-profile (`/profile/personal_access_tokens`); perhaps one for each application
-that needs access to the GitLab API.
-
-Once you have your token, pass it to the API using either the `private_token`
-parameter or the `PRIVATE-TOKEN` header.
+### Private tokens
+Private tokens provide full access to the GitLab API. Anyone with access to
+them can interact with GitLab as if they were you. You can find or reset your
+private token in your account page (`/profile/account`).
-### Session Cookie
+For examples of usage, [read the basic usage section](#basic-usage).
-When signing in to GitLab as an ordinary user, a `_gitlab_session` cookie is
-set. The API will use this cookie for authentication if it is present, but using
-the API to generate a new session cookie is currently not supported.
+### Personal access tokens
-## Basic Usage
+Instead of using your private token which grants full access to your account,
+personal access tokens could be a better fit because of their granular
+permissions.
-API requests should be prefixed with `api` and the API version. The API version
-is defined in [`lib/api.rb`][lib-api-url].
-
-Example of a valid API request:
-
-```shell
-GET https://gitlab.example.com/api/v3/projects?private_token=9koXpg98eAheJpvBs5tK
-```
-
-Example of a valid API request using cURL and authentication via header:
+Once you have your token, pass it to the API using either the `private_token`
+parameter or the `PRIVATE-TOKEN` header. For examples of usage,
+[read the basic usage section](#basic-usage).
-```shell
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects"
-```
+[Read more about personal access tokens.][pat]
-The API uses JSON to serialize data. You don't need to specify `.json` at the
-end of an API URL.
+### Impersonation tokens
-## Status codes
+> [Introduced][ce-9099] in GitLab 9.0. Needs admin permissions.
-The API is designed to return different status codes according to context and
-action. This way, if a request results in an error, the caller is able to get
-insight into what went wrong.
+Impersonation tokens are a type of [personal access token][pat]
+that can only be created by an admin for a specific user.
-The following table gives an overview of how the API functions generally behave.
+They are a better alternative to using the user's password/private token
+or using the [Sudo](#sudo) feature which also requires the admin's password
+or private token, since the password/token can change over time. Impersonation
+tokens are a great fit if you want to build applications or tools which
+authenticate with the API as a specific user.
-| Request type | Description |
-| ------------ | ----------- |
-| `GET` | Access one or more resources and return the result as JSON. |
-| `POST` | Return `201 Created` if the resource is successfully created and return the newly created resource as JSON. |
-| `GET` / `PUT` / `DELETE` | Return `200 OK` if the resource is accessed, modified or deleted successfully. The (modified) result is returned as JSON. |
-| `DELETE` | Designed to be idempotent, meaning a request to a resource still returns `200 OK` even it was deleted before or is not available. The reasoning behind this, is that the user is not really interested if the resource existed before or not. |
+For more information, refer to the
+[users API](users.md#retrieve-user-impersonation-tokens) docs.
-The following table shows the possible return codes for API requests.
+For examples of usage, [read the basic usage section](#basic-usage).
-| Return values | Description |
-| ------------- | ----------- |
-| `200 OK` | The `GET`, `PUT` or `DELETE` request was successful, the resource(s) itself is returned as JSON. |
-| `201 Created` | The `POST` request was successful and the resource is returned as JSON. |
-| `304 Not Modified` | Indicates that the resource has not been modified since the last request. |
-| `400 Bad Request` | A required attribute of the API request is missing, e.g., the title of an issue is not given. |
-| `401 Unauthorized` | The user is not authenticated, a valid [user token](#authentication) is necessary. |
-| `403 Forbidden` | The request is not allowed, e.g., the user is not allowed to delete a project. |
-| `404 Not Found` | A resource could not be accessed, e.g., an ID for a resource could not be found. |
-| `405 Method Not Allowed` | The request is not supported. |
-| `409 Conflict` | A conflicting resource already exists, e.g., creating a project with a name that already exists. |
-| `422 Unprocessable` | The entity could not be processed. |
-| `500 Server Error` | While handling the request something went wrong server-side. |
+### Sudo
-## Sudo
+> Needs admin permissions.
All API requests support performing an API call as if you were another user,
provided your private token is from an administrator account. You need to pass
@@ -189,25 +184,88 @@ returned with status code `404`:
Example of a valid API call and a request using cURL with sudo request,
providing a username:
-```shell
+```
GET /projects?private_token=9koXpg98eAheJpvBs5tK&sudo=username
```
```shell
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "SUDO: username" "https://gitlab.example.com/api/v3/projects"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "SUDO: username" "https://gitlab.example.com/api/v4/projects"
```
Example of a valid API call and a request using cURL with sudo request,
providing an ID:
-```shell
+```
GET /projects?private_token=9koXpg98eAheJpvBs5tK&sudo=23
```
```shell
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "SUDO: 23" "https://gitlab.example.com/api/v3/projects"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "SUDO: 23" "https://gitlab.example.com/api/v4/projects"
```
+## Basic usage
+
+API requests should be prefixed with `api` and the API version. The API version
+is defined in [`lib/api.rb`][lib-api-url].
+
+For endpoints that require [authentication](#authentication), you need to pass
+a `private_token` parameter via query string or header. If passed as a header,
+the header name must be `PRIVATE-TOKEN` (uppercase and with a dash instead of
+an underscore).
+
+Example of a valid API request:
+
+```
+GET /projects?private_token=9koXpg98eAheJpvBs5tK
+```
+
+Example of a valid API request using cURL and authentication via header:
+
+```shell
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects"
+```
+
+Example of a valid API request using cURL and authentication via a query string:
+
+```shell
+curl "https://gitlab.example.com/api/v4/projects?private_token=9koXpg98eAheJpvBs5tK"
+```
+
+The API uses JSON to serialize data. You don't need to specify `.json` at the
+end of an API URL.
+
+## Status codes
+
+The API is designed to return different status codes according to context and
+action. This way, if a request results in an error, the caller is able to get
+insight into what went wrong.
+
+The following table gives an overview of how the API functions generally behave.
+
+| Request type | Description |
+| ------------ | ----------- |
+| `GET` | Access one or more resources and return the result as JSON. |
+| `POST` | Return `201 Created` if the resource is successfully created and return the newly created resource as JSON. |
+| `GET` / `PUT` / `DELETE` | Return `200 OK` if the resource is accessed, modified or deleted successfully. The (modified) result is returned as JSON. |
+| `DELETE` | Designed to be idempotent, meaning a request to a resource still returns `200 OK` even it was deleted before or is not available. The reasoning behind this, is that the user is not really interested if the resource existed before or not. |
+
+The following table shows the possible return codes for API requests.
+
+| Return values | Description |
+| ------------- | ----------- |
+| `200 OK` | The `GET`, `PUT` or `DELETE` request was successful, the resource(s) itself is returned as JSON. |
+| `204 No Content` | The server has successfully fulfilled the request and that there is no additional content to send in the response payload body. |
+| `201 Created` | The `POST` request was successful and the resource is returned as JSON. |
+| `304 Not Modified` | Indicates that the resource has not been modified since the last request. |
+| `400 Bad Request` | A required attribute of the API request is missing, e.g., the title of an issue is not given. |
+| `401 Unauthorized` | The user is not authenticated, a valid [user token](#authentication) is necessary. |
+| `403 Forbidden` | The request is not allowed, e.g., the user is not allowed to delete a project. |
+| `404 Not Found` | A resource could not be accessed, e.g., an ID for a resource could not be found. |
+| `405 Method Not Allowed` | The request is not supported. |
+| `409 Conflict` | A conflicting resource already exists, e.g., creating a project with a name that already exists. |
+| `422 Unprocessable` | The entity could not be processed. |
+| `500 Server Error` | While handling the request something went wrong server-side. |
+
## Pagination
Sometimes the returned result will span across many pages. When listing
@@ -221,7 +279,7 @@ resources you can pass the following parameters:
In the example below, we list 50 [namespaces](namespaces.md) per page.
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/namespaces?per_page=50
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/namespaces?per_page=50
```
### Pagination Link header
@@ -235,7 +293,7 @@ and we request the second page (`page=2`) of [comments](notes.md) of the issue
with ID `8` which belongs to the project with ID `8`:
```bash
-curl --head --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/8/issues/8/notes?per_page=3&page=2
+curl --head --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/8/issues/8/notes?per_page=3&page=2
```
The response will then be:
@@ -246,7 +304,7 @@ Cache-Control: no-cache
Content-Length: 1103
Content-Type: application/json
Date: Mon, 18 Jan 2016 09:43:18 GMT
-Link: <https://gitlab.example.com/api/v3/projects/8/issues/8/notes?page=1&per_page=3>; rel="prev", <https://gitlab.example.com/api/v3/projects/8/issues/8/notes?page=3&per_page=3>; rel="next", <https://gitlab.example.com/api/v3/projects/8/issues/8/notes?page=1&per_page=3>; rel="first", <https://gitlab.example.com/api/v3/projects/8/issues/8/notes?page=3&per_page=3>; rel="last"
+Link: <https://gitlab.example.com/api/v4/projects/8/issues/8/notes?page=1&per_page=3>; rel="prev", <https://gitlab.example.com/api/v4/projects/8/issues/8/notes?page=3&per_page=3>; rel="next", <https://gitlab.example.com/api/v4/projects/8/issues/8/notes?page=1&per_page=3>; rel="first", <https://gitlab.example.com/api/v4/projects/8/issues/8/notes?page=3&per_page=3>; rel="last"
Status: 200 OK
Vary: Origin
X-Next-Page: 3
@@ -272,6 +330,17 @@ Additional pagination headers are also sent back.
| `X-Next-Page` | The index of the next page |
| `X-Prev-Page` | The index of the previous page |
+## Namespaced path encoding
+
+If using namespaced API calls, make sure that the `NAMESPACE/PROJECT_NAME` is
+URL-encoded.
+
+For example, `/` is represented by `%2F`:
+
+```
+/api/v4/projects/diaspora%2Fdiaspora
+```
+
## `id` vs `iid`
When you work with the API, you may notice two similar fields in API entities:
@@ -286,14 +355,14 @@ For example, an issue might have `id: 46` and `iid: 5`.
That means that if you want to get an issue via the API you should use the `id`:
-```bash
+```
GET /projects/42/issues/:id
```
On the other hand, if you want to create a link to a web page you should use
the `iid`:
-```bash
+```
GET /projects/42/issues/:iid
```
@@ -355,6 +424,18 @@ follows:
}
```
+## Unknown route
+
+When you try to access an API URL that does not exist you will receive 404 Not Found.
+
+```
+HTTP/1.1 404 Not Found
+Content-Type: application/json
+{
+ "error": "404 Not Found"
+}
+```
+
## Clients
There are many unofficial GitLab API Clients for most of the popular
@@ -363,3 +444,6 @@ programming languages. Visit the [GitLab website] for a complete list.
[GitLab website]: https://about.gitlab.com/applications/#api-clients "Clients using the GitLab API"
[lib-api-url]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/api/api.rb
[ce-3749]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3749
+[ce-5951]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5951
+[ce-9099]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9099
+[pat]: ../user/profile/personal_access_tokens.md
diff --git a/doc/api/access_requests.md b/doc/api/access_requests.md
index ea308b54d62..603fa4a8194 100644
--- a/doc/api/access_requests.md
+++ b/doc/api/access_requests.md
@@ -1,4 +1,4 @@
-# Group and project access requests
+# Group and project access requests API
>**Note:** This feature was introduced in GitLab 8.11
@@ -18,8 +18,6 @@
Gets a list of access requests viewable by the authenticated user.
-Returns `200` if the request succeeds.
-
```
GET /groups/:id/access_requests
GET /projects/:id/access_requests
@@ -27,11 +25,11 @@ GET /projects/:id/access_requests
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The group/project ID or path |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/:id/access_requests
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/:id/access_requests
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/access_requests
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/access_requests
```
Example response:
@@ -61,8 +59,6 @@ Example response:
Requests access for the authenticated user to a group or project.
-Returns `201` if the request succeeds.
-
```
POST /groups/:id/access_requests
POST /projects/:id/access_requests
@@ -70,11 +66,11 @@ POST /projects/:id/access_requests
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The group/project ID or path |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/:id/access_requests
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/:id/access_requests
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/access_requests
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/access_requests
```
Example response:
@@ -94,8 +90,6 @@ Example response:
Approves an access request for the given user.
-Returns `201` if the request succeeds.
-
```
PUT /groups/:id/access_requests/:user_id/approve
PUT /projects/:id/access_requests/:user_id/approve
@@ -103,13 +97,13 @@ PUT /projects/:id/access_requests/:user_id/approve
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The group/project ID or path |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `user_id` | integer | yes | The user ID of the access requester |
| `access_level` | integer | no | A valid access level (defaults: `30`, developer access level) |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/:id/access_requests/:user_id/approve?access_level=20
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/:id/access_requests/:user_id/approve?access_level=20
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/access_requests/:user_id/approve?access_level=20
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/access_requests/:user_id/approve?access_level=20
```
Example response:
@@ -129,8 +123,6 @@ Example response:
Denies an access request for the given user.
-Returns `200` if the request succeeds.
-
```
DELETE /groups/:id/access_requests/:user_id
DELETE /projects/:id/access_requests/:user_id
@@ -138,10 +130,10 @@ DELETE /projects/:id/access_requests/:user_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The group/project ID or path |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `user_id` | integer | yes | The user ID of the access requester |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/:id/access_requests/:user_id
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/:id/access_requests/:user_id
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/access_requests/:user_id
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/access_requests/:user_id
```
diff --git a/doc/api/award_emoji.md b/doc/api/award_emoji.md
index c464e3f3f71..d6924741ee4 100644
--- a/doc/api/award_emoji.md
+++ b/doc/api/award_emoji.md
@@ -1,4 +1,4 @@
-# Award Emoji
+# Award Emoji API
> [Introduced][ce-4575] in GitLab 8.9, Snippet support in 8.12
@@ -14,20 +14,20 @@ requests, snippets, and notes/comments. Issues, merge requests, snippets, and no
Gets a list of all award emoji
```
-GET /projects/:id/issues/:issue_id/award_emoji
-GET /projects/:id/merge_requests/:merge_request_id/award_emoji
+GET /projects/:id/issues/:issue_iid/award_emoji
+GET /projects/:id/merge_requests/:merge_request_iid/award_emoji
GET /projects/:id/snippets/:snippet_id/award_emoji
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `awardable_id` | integer | yes | The ID of an awardable |
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `awardable_id` | integer | yes | The ID (`iid` for merge requests/issues, `id` for snippets) of an awardable |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" http://gitlab.example.com/api/v3/projects/1/issues/80/award_emoji
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji
```
Example Response:
@@ -43,7 +43,7 @@ Example Response:
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://gitlab.example.com/u/root"
+ "web_url": "http://gitlab.example.com/root"
},
"created_at": "2016-06-15T10:09:34.206Z",
"updated_at": "2016-06-15T10:09:34.206Z",
@@ -59,7 +59,7 @@ Example Response:
"id": 26,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/7e65550957227bd38fe2d7fbc6fd2f7b?s=80&d=identicon",
- "web_url": "http://gitlab.example.com/u/user4"
+ "web_url": "http://gitlab.example.com/user4"
},
"created_at": "2016-06-15T10:09:34.177Z",
"updated_at": "2016-06-15T10:09:34.177Z",
@@ -74,21 +74,21 @@ Example Response:
Gets a single award emoji from an issue, snippet, or merge request.
```
-GET /projects/:id/issues/:issue_id/award_emoji/:award_id
-GET /projects/:id/merge_requests/:merge_request_id/award_emoji/:award_id
+GET /projects/:id/issues/:issue_iid/award_emoji/:award_id
+GET /projects/:id/merge_requests/:merge_request_iid/award_emoji/:award_id
GET /projects/:id/snippets/:snippet_id/award_emoji/:award_id
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `awardable_id` | integer | yes | The ID of an awardable |
-| `award_id` | integer | yes | The ID of the award emoji |
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `awardable_id` | integer | yes | The ID (`iid` for merge requests/issues, `id` for snippets) of an awardable |
+| `award_id` | integer | yes | The ID of the award emoji |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" http://gitlab.example.com/api/v3/projects/1/issues/80/award_emoji/1
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/1
```
Example Response:
@@ -103,7 +103,7 @@ Example Response:
"id": 26,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/7e65550957227bd38fe2d7fbc6fd2f7b?s=80&d=identicon",
- "web_url": "http://gitlab.example.com/u/user4"
+ "web_url": "http://gitlab.example.com/user4"
},
"created_at": "2016-06-15T10:09:34.177Z",
"updated_at": "2016-06-15T10:09:34.177Z",
@@ -117,21 +117,21 @@ Example Response:
This end point creates an award emoji on the specified resource
```
-POST /projects/:id/issues/:issue_id/award_emoji
-POST /projects/:id/merge_requests/:merge_request_id/award_emoji
+POST /projects/:id/issues/:issue_iid/award_emoji
+POST /projects/:id/merge_requests/:merge_request_iid/award_emoji
POST /projects/:id/snippets/:snippet_id/award_emoji
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `awardable_id` | integer | yes | The ID of an awardable |
-| `name` | string | yes | The name of the emoji, without colons |
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `awardable_id` | integer | yes | The ID (`iid` for merge requests/issues, `id` for snippets) of an awardable |
+| `name` | string | yes | The name of the emoji, without colons |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" http://gitlab.example.com/api/v3/projects/1/issues/80/award_emoji?name=blowfish
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji?name=blowfish
```
Example Response:
@@ -146,57 +146,36 @@ Example Response:
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://gitlab.example.com/u/root"
+ "web_url": "http://gitlab.example.com/root"
},
"created_at": "2016-06-17T17:47:29.266Z",
"updated_at": "2016-06-17T17:47:29.266Z",
"awardable_id": 80,
"awardable_type": "Issue"
-}
+}
```
### Delete an award emoji
Sometimes its just not meant to be, and you'll have to remove your award. Only available to
-admins or the author of the award. Status code 200 on success, 401 if unauthorized.
+admins or the author of the award.
```
-DELETE /projects/:id/issues/:issue_id/award_emoji/:award_id
-DELETE /projects/:id/merge_requests/:merge_request_id/award_emoji/:award_id
+DELETE /projects/:id/issues/:issue_iid/award_emoji/:award_id
+DELETE /projects/:id/merge_requests/:merge_request_iid/award_emoji/:award_id
DELETE /projects/:id/snippets/:snippet_id/award_emoji/:award_id
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `issue_id` | integer | yes | The ID of an issue |
-| `award_id` | integer | yes | The ID of a award_emoji |
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of an issue |
+| `award_id` | integer | yes | The ID of a award_emoji |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" http://gitlab.example.com/api/v3/projects/1/issues/80/award_emoji/344
-```
-
-Example Response:
-
-```json
-{
- "id": 344,
- "name": "blowfish",
- "user": {
- "name": "Administrator",
- "username": "root",
- "id": 1,
- "state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://gitlab.example.com/u/root"
- },
- "created_at": "2016-06-17T17:47:29.266Z",
- "updated_at": "2016-06-17T17:47:29.266Z",
- "awardable_id": 80,
- "awardable_type": "Issue"
-}
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/344
```
## Award Emoji on Notes
@@ -209,20 +188,20 @@ easily adapted for notes on a Merge Request.
### List a note's award emoji
```
-GET /projects/:id/issues/:issue_id/notes/:note_id/award_emoji
+GET /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `issue_id` | integer | yes | The ID of an issue |
-| `note_id` | integer | yes | The ID of an note |
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of an issue |
+| `note_id` | integer | yes | The ID of an note |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" http://gitlab.example.com/api/v3/projects/1/issues/80/notes/1/award_emoji
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji
```
Example Response:
@@ -238,7 +217,7 @@ Example Response:
"id": 26,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/7e65550957227bd38fe2d7fbc6fd2f7b?s=80&d=identicon",
- "web_url": "http://gitlab.example.com/u/user4"
+ "web_url": "http://gitlab.example.com/user4"
},
"created_at": "2016-06-15T10:09:34.197Z",
"updated_at": "2016-06-15T10:09:34.197Z",
@@ -251,20 +230,20 @@ Example Response:
### Get single note's award emoji
```
-GET /projects/:id/issues/:issue_id/notes/:note_id/award_emoji/:award_id
+GET /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji/:award_id
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `issue_id` | integer | yes | The ID of an issue |
-| `note_id` | integer | yes | The ID of a note |
-| `award_id` | integer | yes | The ID of the award emoji |
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of an issue |
+| `note_id` | integer | yes | The ID of a note |
+| `award_id` | integer | yes | The ID of the award emoji |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" http://gitlab.example.com/api/v3/projects/1/issues/80/notes/1/award_emoji/2
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji/2
```
Example Response:
@@ -279,7 +258,7 @@ Example Response:
"id": 26,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/7e65550957227bd38fe2d7fbc6fd2f7b?s=80&d=identicon",
- "web_url": "http://gitlab.example.com/u/user4"
+ "web_url": "http://gitlab.example.com/user4"
},
"created_at": "2016-06-15T10:09:34.197Z",
"updated_at": "2016-06-15T10:09:34.197Z",
@@ -291,20 +270,20 @@ Example Response:
### Award a new emoji on a note
```
-POST /projects/:id/issues/:issue_id/notes/:note_id/award_emoji
+POST /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `issue_id` | integer | yes | The ID of an issue |
-| `note_id` | integer | yes | The ID of a note |
-| `name` | string | yes | The name of the emoji, without colons |
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of an issue |
+| `note_id` | integer | yes | The ID of a note |
+| `name` | string | yes | The name of the emoji, without colons |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" http://gitlab.example.com/api/v3/projects/1/issues/80/notes/1/award_emoji?name=rocket
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/notes/1/award_emoji?name=rocket
```
Example Response:
@@ -319,7 +298,7 @@ Example Response:
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://gitlab.example.com/u/root"
+ "web_url": "http://gitlab.example.com/root"
},
"created_at": "2016-06-17T19:59:55.888Z",
"updated_at": "2016-06-17T19:59:55.888Z",
@@ -331,44 +310,23 @@ Example Response:
### Delete an award emoji
Sometimes its just not meant to be, and you'll have to remove your award. Only available to
-admins or the author of the award. Status code 200 on success, 401 if unauthorized.
+admins or the author of the award.
```
-DELETE /projects/:id/issues/:issue_id/notes/:note_id/award_emoji/:award_id
+DELETE /projects/:id/issues/:issue_iid/notes/:note_id/award_emoji/:award_id
```
Parameters:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `issue_id` | integer | yes | The ID of an issue |
-| `note_id` | integer | yes | The ID of a note |
-| `award_id` | integer | yes | The ID of a award_emoji |
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of an issue |
+| `note_id` | integer | yes | The ID of a note |
+| `award_id` | integer | yes | The ID of a award_emoji |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" http://gitlab.example.com/api/v3/projects/1/issues/80/award_emoji/345
-```
-
-Example Response:
-
-```json
-{
- "id": 345,
- "name": "rocket",
- "user": {
- "name": "Administrator",
- "username": "root",
- "id": 1,
- "state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://gitlab.example.com/u/root"
- },
- "created_at": "2016-06-17T19:59:55.888Z",
- "updated_at": "2016-06-17T19:59:55.888Z",
- "awardable_id": 1,
- "awardable_type": "Note"
-}
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/80/award_emoji/345
```
[ce-4575]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4575
diff --git a/doc/api/boards.md b/doc/api/boards.md
index 28681719f43..69c47abc806 100644
--- a/doc/api/boards.md
+++ b/doc/api/boards.md
@@ -1,4 +1,4 @@
-# Boards
+# Issue Boards API
Every API call to boards must be authenticated.
@@ -15,10 +15,10 @@ GET /projects/:id/boards
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/:id/boards
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/boards
```
Example response:
@@ -63,7 +63,7 @@ Example response:
## List board lists
Get a list of the board's lists.
-Does not include `backlog` and `done` lists
+Does not include `backlog` and `closed` lists
```
GET /projects/:id/boards/:board_id/lists
@@ -71,11 +71,11 @@ GET /projects/:id/boards/:board_id/lists
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `board_id` | integer | yes | The ID of a board |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/boards/1/lists
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/boards/1/lists
```
Example response:
@@ -122,12 +122,12 @@ GET /projects/:id/boards/:board_id/lists/:list_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `board_id` | integer | yes | The ID of a board |
| `list_id`| integer | yes | The ID of a board's list |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/boards/1/lists/1
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1
```
Example response:
@@ -148,22 +148,18 @@ Example response:
Creates a new Issue Board list.
-If the operation is successful, a status code of `200` and the newly-created
-list is returned. If an error occurs, an error number and a message explaining
-the reason is returned.
-
```
POST /projects/:id/boards/:board_id/lists
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `board_id` | integer | yes | The ID of a board |
| `label_id` | integer | yes | The ID of a label |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/boards/1/lists?label_id=5
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/boards/1/lists?label_id=5
```
Example response:
@@ -184,23 +180,19 @@ Example response:
Updates an existing Issue Board list. This call is used to change list position.
-If the operation is successful, a code of `200` and the updated board list is
-returned. If an error occurs, an error number and a message explaining the
-reason is returned.
-
```
PUT /projects/:id/boards/:board_id/lists/:list_id
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `board_id` | integer | yes | The ID of a board |
| `list_id` | integer | yes | The ID of a board's list |
| `position` | integer | yes | The position of the list |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/boards/1/lists/1?position=2
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1?position=2
```
Example response:
@@ -220,8 +212,6 @@ Example response:
## Delete a board list
Only for admins and project owners. Soft deletes the board list in question.
-If the operation is successful, a status code `200` is returned. In case you cannot
-destroy this board list, or it is not present, code `404` is given.
```
DELETE /projects/:id/boards/:board_id/lists/:list_id
@@ -229,23 +219,10 @@ DELETE /projects/:id/boards/:board_id/lists/:list_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `board_id` | integer | yes | The ID of a board |
| `list_id` | integer | yes | The ID of a board's list |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/boards/1/lists/1
-```
-Example response:
-
-```json
-{
- "id" : 1,
- "label" : {
- "name" : "Testing",
- "color" : "#F0AD4E",
- "description" : null
- },
- "position" : 1
-}
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1
```
diff --git a/doc/api/branches.md b/doc/api/branches.md
index 0b5f7778fc7..dfaa7d6fab7 100644
--- a/doc/api/branches.md
+++ b/doc/api/branches.md
@@ -1,8 +1,10 @@
-# Branches
+# Branches API
## List repository branches
Get a list of repository branches from a project, sorted by name alphabetically.
+This endpoint can be accessed without authentication if the repository is
+publicly accessible.
```
GET /projects/:id/repository/branches
@@ -10,10 +12,10 @@ GET /projects/:id/repository/branches
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/repository/branches
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/repository/branches
```
Example response:
@@ -22,6 +24,7 @@ Example response:
[
{
"name": "master",
+ "merged": false,
"protected": true,
"developers_can_push": false,
"developers_can_merge": false,
@@ -33,6 +36,8 @@ Example response:
"committer_email": "john@example.com",
"committer_name": "John Smith",
"id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
+ "short_id": "7b5c3cc",
+ "title": "add projects API",
"message": "add projects API",
"parent_ids": [
"4ad91d3c1144c406e50c7b33bae684bd6837faf8"
@@ -45,7 +50,8 @@ Example response:
## Get single repository branch
-Get a single project repository branch.
+Get a single project repository branch. This endpoint can be accessed without
+authentication if the repository is publicly accessible.
```
GET /projects/:id/repository/branches/:branch
@@ -53,11 +59,11 @@ GET /projects/:id/repository/branches/:branch
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `branch` | string | yes | The name of the branch |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/repository/branches/master
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/repository/branches/master
```
Example response:
@@ -65,6 +71,7 @@ Example response:
```json
{
"name": "master",
+ "merged": false,
"protected": true,
"developers_can_push": false,
"developers_can_merge": false,
@@ -76,6 +83,8 @@ Example response:
"committer_email": "john@example.com",
"committer_name": "John Smith",
"id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
+ "short_id": "7b5c3cc",
+ "title": "add projects API",
"message": "add projects API",
"parent_ids": [
"4ad91d3c1144c406e50c7b33bae684bd6837faf8"
@@ -95,12 +104,12 @@ PUT /projects/:id/repository/branches/:branch/protect
```
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/repository/branches/master/protect?developers_can_push=true&developers_can_merge=true
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/repository/branches/master/protect?developers_can_push=true&developers_can_merge=true
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `branch` | string | yes | The name of the branch |
| `developers_can_push` | boolean | no | Flag if developers can push to the branch |
| `developers_can_merge` | boolean | no | Flag if developers can merge to the branch |
@@ -117,12 +126,15 @@ Example response:
"committer_email": "john@example.com",
"committer_name": "John Smith",
"id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
+ "short_id": "7b5c3cc",
+ "title": "add projects API",
"message": "add projects API",
"parent_ids": [
"4ad91d3c1144c406e50c7b33bae684bd6837faf8"
]
},
"name": "master",
+ "merged": false,
"protected": true,
"developers_can_push": true,
"developers_can_merge": true
@@ -140,12 +152,12 @@ PUT /projects/:id/repository/branches/:branch/unprotect
```
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/repository/branches/master/unprotect
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/repository/branches/master/unprotect
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `branch` | string | yes | The name of the branch |
Example response:
@@ -160,12 +172,15 @@ Example response:
"committer_email": "john@example.com",
"committer_name": "John Smith",
"id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
+ "short_id": "7b5c3cc",
+ "title": "add projects API",
"message": "add projects API",
"parent_ids": [
"4ad91d3c1144c406e50c7b33bae684bd6837faf8"
]
},
"name": "master",
+ "merged": false,
"protected": false,
"developers_can_push": false,
"developers_can_merge": false
@@ -180,12 +195,12 @@ POST /projects/:id/repository/branches
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `branch_name` | string | yes | The name of the branch |
+| `id` | integer | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `branch` | string | yes | The name of the branch |
| `ref` | string | yes | The branch name or commit SHA to create branch from |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/repository/branches?branch_name=newbranch&ref=master"
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/branches?branch=newbranch&ref=master"
```
Example response:
@@ -200,21 +215,21 @@ Example response:
"committer_email": "john@example.com",
"committer_name": "John Smith",
"id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
+ "short_id": "7b5c3cc",
+ "title": "add projects API",
"message": "add projects API",
"parent_ids": [
"4ad91d3c1144c406e50c7b33bae684bd6837faf8"
]
},
"name": "newbranch",
+ "merged": false,
"protected": false,
"developers_can_push": false,
"developers_can_merge": false
}
```
-It returns `200` if it succeeds or `400` if failed with an error message
-explaining the reason.
-
## Delete repository branch
```
@@ -223,20 +238,30 @@ DELETE /projects/:id/repository/branches/:branch
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `branch` | string | yes | The name of the branch |
-It returns `200` if it succeeds, `404` if the branch to be deleted does not exist
-or `400` for other reasons. In case of an error, an explaining message is provided.
+In case of an error, an explaining message is provided.
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/repository/branches/newbranch"
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/branches/newbranch"
```
-Example response:
+## Delete merged branches
-```json
-{
- "branch_name": "newbranch"
-}
+Will delete all branches that are merged into the project's default branch.
+
+Protected branches will not be deleted as part of this operation.
+
+```
+DELETE /projects/:id/repository/merged_branches
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+
+
+```bash
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/merged_branches"
```
diff --git a/doc/api/broadcast_messages.md b/doc/api/broadcast_messages.md
index c3a9207a3ae..a8a248a17f4 100644
--- a/doc/api/broadcast_messages.md
+++ b/doc/api/broadcast_messages.md
@@ -1,4 +1,4 @@
-# Broadcast Messages
+# Broadcast Messages API
> **Note:** This feature was introduced in GitLab 8.12.
@@ -13,7 +13,7 @@ GET /broadcast_messages
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/broadcast_messages
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/broadcast_messages
```
Example response:
@@ -43,7 +43,7 @@ GET /broadcast_messages/:id
| `id` | integer | yes | Broadcast message ID |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/broadcast_messages/1
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/broadcast_messages/1
```
Example response:
@@ -62,10 +62,6 @@ Example response:
## Create a broadcast message
-Responds with `400 Bad request` when the `message` parameter is missing or the
-`color` or `font` values are invalid, and `201 Created` when the broadcast
-message was successfully created.
-
```
POST /broadcast_messages
```
@@ -79,7 +75,7 @@ POST /broadcast_messages
| `font` | string | no | Foreground color hex code |
```bash
-curl --data "message=Deploy in progress&color=#cecece" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/broadcast_messages
+curl --data "message=Deploy in progress&color=#cecece" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/broadcast_messages
```
Example response:
@@ -112,7 +108,7 @@ PUT /broadcast_messages/:id
| `font` | string | no | Foreground color hex code |
```bash
-curl --request PUT --data "message=Update message&color=#000" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/broadcast_messages/1
+curl --request PUT --data "message=Update message&color=#000" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/broadcast_messages/1
```
Example response:
@@ -140,19 +136,5 @@ DELETE /broadcast_messages/:id
| `id` | integer | yes | Broadcast message ID |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/broadcast_messages/1
-```
-
-Example response:
-
-```json
-{
- "message":"Update message",
- "starts_at":"2016-08-26T00:41:35.060Z",
- "ends_at":"2016-08-26T01:41:35.060Z",
- "color":"#000",
- "font":"#FFFFFF",
- "id":1,
- "active": true
-}
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/broadcast_messages/1
```
diff --git a/doc/api/build_triggers.md b/doc/api/build_triggers.md
index 1b7a1840138..20d924ab35e 100644
--- a/doc/api/build_triggers.md
+++ b/doc/api/build_triggers.md
@@ -1,118 +1 @@
-# Build triggers
-
-You can read more about [triggering builds through the API](../ci/triggers/README.md).
-
-## List project triggers
-
-Get a list of project's build triggers.
-
-```
-GET /projects/:id/triggers
-```
-
-| Attribute | Type | required | Description |
-|-----------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
-
-```
-curl --header "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/triggers"
-```
-
-```json
-[
- {
- "created_at": "2015-12-23T16:24:34.716Z",
- "deleted_at": null,
- "last_used": "2016-01-04T15:41:21.986Z",
- "token": "fbdb730c2fbdb095a0862dbd8ab88b",
- "updated_at": "2015-12-23T16:24:34.716Z"
- },
- {
- "created_at": "2015-12-23T16:25:56.760Z",
- "deleted_at": null,
- "last_used": null,
- "token": "7b9148c158980bbd9bcea92c17522d",
- "updated_at": "2015-12-23T16:25:56.760Z"
- }
-]
-```
-
-## Get trigger details
-
-Get details of project's build trigger.
-
-```
-GET /projects/:id/triggers/:token
-```
-
-| Attribute | Type | required | Description |
-|-----------|---------|----------|--------------------------|
-| `id` | integer | yes | The ID of a project |
-| `token` | string | yes | The `token` of a trigger |
-
-```
-curl --header "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/triggers/7b9148c158980bbd9bcea92c17522d"
-```
-
-```json
-{
- "created_at": "2015-12-23T16:25:56.760Z",
- "deleted_at": null,
- "last_used": null,
- "token": "7b9148c158980bbd9bcea92c17522d",
- "updated_at": "2015-12-23T16:25:56.760Z"
-}
-```
-
-## Create a project trigger
-
-Create a build trigger for a project.
-
-```
-POST /projects/:id/triggers
-```
-
-| Attribute | Type | required | Description |
-|-----------|---------|----------|--------------------------|
-| `id` | integer | yes | The ID of a project |
-
-```
-curl --request POST --header "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/triggers"
-```
-
-```json
-{
- "created_at": "2016-01-07T09:53:58.235Z",
- "deleted_at": null,
- "last_used": null,
- "token": "6d056f63e50fe6f8c5f8f4aa10edb7",
- "updated_at": "2016-01-07T09:53:58.235Z"
-}
-```
-
-## Remove a project trigger
-
-Remove a project's build trigger.
-
-```
-DELETE /projects/:id/triggers/:token
-```
-
-| Attribute | Type | required | Description |
-|-----------|---------|----------|--------------------------|
-| `id` | integer | yes | The ID of a project |
-| `token` | string | yes | The `token` of a trigger |
-
-```
-curl --request DELETE --header "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/triggers/7b9148c158980bbd9bcea92c17522d"
-```
-
-```json
-{
- "created_at": "2015-12-23T16:25:56.760Z",
- "deleted_at": "2015-12-24T12:32:20.100Z",
- "last_used": null,
- "token": "7b9148c158980bbd9bcea92c17522d",
- "updated_at": "2015-12-24T12:32:20.100Z"
-}
-```
+This document was moved to [Pipeline Triggers](pipeline_triggers.md).
diff --git a/doc/api/build_variables.md b/doc/api/build_variables.md
index a21751a49ea..d4f00256ed3 100644
--- a/doc/api/build_variables.md
+++ b/doc/api/build_variables.md
@@ -1,4 +1,4 @@
-# Build Variables
+# Build Variables API
## List project variables
@@ -10,10 +10,10 @@ GET /projects/:id/variables
| Attribute | Type | required | Description |
|-----------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```
-curl --header "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/variables"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/variables"
```
```json
@@ -39,11 +39,11 @@ GET /projects/:id/variables/:key
| Attribute | Type | required | Description |
|-----------|---------|----------|-----------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `key` | string | yes | The `key` of a variable |
```
-curl --header "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/variables/TEST_VARIABLE_1"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/variables/TEST_VARIABLE_1"
```
```json
@@ -61,20 +61,22 @@ Create a new build variable.
POST /projects/:id/variables
```
-| Attribute | Type | required | Description |
-|-----------|---------|----------|-----------------------|
-| `id` | integer | yes | The ID of a project |
-| `key` | string | yes | The `key` of a variable; must have no more than 255 characters; only `A-Z`, `a-z`, `0-9`, and `_` are allowed |
-| `value` | string | yes | The `value` of a variable |
+| Attribute | Type | required | Description |
+|-------------|---------|----------|-----------------------|
+| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `key` | string | yes | The `key` of a variable; must have no more than 255 characters; only `A-Z`, `a-z`, `0-9`, and `_` are allowed |
+| `value` | string | yes | The `value` of a variable |
+| `protected` | boolean | no | Whether the variable is protected |
```
-curl --request POST --header "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/variables" --form "key=NEW_VARIABLE" --form "value=new value"
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/variables" --form "key=NEW_VARIABLE" --form "value=new value"
```
```json
{
"key": "NEW_VARIABLE",
- "value": "new value"
+ "value": "new value",
+ "protected": false
}
```
@@ -86,20 +88,22 @@ Update a project's build variable.
PUT /projects/:id/variables/:key
```
-| Attribute | Type | required | Description |
-|-----------|---------|----------|-------------------------|
-| `id` | integer | yes | The ID of a project |
-| `key` | string | yes | The `key` of a variable |
-| `value` | string | yes | The `value` of a variable |
+| Attribute | Type | required | Description |
+|-------------|---------|----------|-------------------------|
+| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `key` | string | yes | The `key` of a variable |
+| `value` | string | yes | The `value` of a variable |
+| `protected` | boolean | no | Whether the variable is protected |
```
-curl --request PUT --header "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/variables/NEW_VARIABLE" --form "value=updated value"
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/variables/NEW_VARIABLE" --form "value=updated value"
```
```json
{
"key": "NEW_VARIABLE",
- "value": "updated value"
+ "value": "updated value",
+ "protected": true
}
```
@@ -113,16 +117,9 @@ DELETE /projects/:id/variables/:key
| Attribute | Type | required | Description |
|-----------|---------|----------|-------------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `key` | string | yes | The `key` of a variable |
```
-curl --request DELETE --header "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/variables/VARIABLE_1"
-```
-
-```json
-{
- "key": "VARIABLE_1",
- "value": "VALUE_1"
-}
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/variables/VARIABLE_1"
```
diff --git a/doc/api/builds.md b/doc/api/builds.md
index e8a9e4743d3..a6edda68bc4 100644
--- a/doc/api/builds.md
+++ b/doc/api/builds.md
@@ -1,610 +1 @@
-# Builds API
-
-## List project builds
-
-Get a list of builds in a project.
-
-```
-GET /projects/:id/builds
-```
-
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
-| `scope` | string **or** array of strings | no | The scope of builds to show, one or array of: `pending`, `running`, `failed`, `success`, `canceled`; showing all builds if none provided |
-
-```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/builds"
-```
-
-Example of response
-
-```json
-[
- {
- "commit": {
- "author_email": "admin@example.com",
- "author_name": "Administrator",
- "created_at": "2015-12-24T16:51:14.000+01:00",
- "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "message": "Test the CI integration.",
- "short_id": "0ff3ae19",
- "title": "Test the CI integration."
- },
- "coverage": null,
- "created_at": "2015-12-24T15:51:21.802Z",
- "artifacts_file": {
- "filename": "artifacts.zip",
- "size": 1000
- },
- "finished_at": "2015-12-24T17:54:27.895Z",
- "id": 7,
- "name": "teaspoon",
- "pipeline": {
- "id": 6,
- "ref": "master",
- "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "status": "pending"
- }
- "ref": "master",
- "runner": null,
- "stage": "test",
- "started_at": "2015-12-24T17:54:27.722Z",
- "status": "failed",
- "tag": false,
- "user": {
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "bio": null,
- "created_at": "2015-12-21T13:14:24.077Z",
- "id": 1,
- "is_admin": true,
- "linkedin": "",
- "name": "Administrator",
- "skype": "",
- "state": "active",
- "twitter": "",
- "username": "root",
- "web_url": "http://gitlab.dev/u/root",
- "website_url": ""
- }
- },
- {
- "commit": {
- "author_email": "admin@example.com",
- "author_name": "Administrator",
- "created_at": "2015-12-24T16:51:14.000+01:00",
- "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "message": "Test the CI integration.",
- "short_id": "0ff3ae19",
- "title": "Test the CI integration."
- },
- "coverage": null,
- "created_at": "2015-12-24T15:51:21.727Z",
- "artifacts_file": null,
- "finished_at": "2015-12-24T17:54:24.921Z",
- "id": 6,
- "name": "spinach:other",
- "pipeline": {
- "id": 6,
- "ref": "master",
- "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "status": "pending"
- }
- "ref": "master",
- "runner": null,
- "stage": "test",
- "started_at": "2015-12-24T17:54:24.729Z",
- "status": "failed",
- "tag": false,
- "user": {
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "bio": null,
- "created_at": "2015-12-21T13:14:24.077Z",
- "id": 1,
- "is_admin": true,
- "linkedin": "",
- "name": "Administrator",
- "skype": "",
- "state": "active",
- "twitter": "",
- "username": "root",
- "web_url": "http://gitlab.dev/u/root",
- "website_url": ""
- }
- }
-]
-```
-
-## List commit builds
-
-Get a list of builds for specific commit in a project.
-
-This endpoint will return all builds, from all pipelines for a given commit.
-If the commit SHA is not found, it will respond with 404, otherwise it will
-return an array of builds (an empty array if there are no builds for this
-particular commit).
-
-```
-GET /projects/:id/repository/commits/:sha/builds
-```
-
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
-| `sha` | string | yes | The SHA id of a commit |
-| `scope` | string **or** array of strings | no | The scope of builds to show, one or array of: `pending`, `running`, `failed`, `success`, `canceled`; showing all builds if none provided |
-
-```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/repository/commits/0ff3ae198f8601a285adcf5c0fff204ee6fba5fd/builds"
-```
-
-Example of response
-
-```json
-[
- {
- "commit": {
- "author_email": "admin@example.com",
- "author_name": "Administrator",
- "created_at": "2015-12-24T16:51:14.000+01:00",
- "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "message": "Test the CI integration.",
- "short_id": "0ff3ae19",
- "title": "Test the CI integration."
- },
- "coverage": null,
- "created_at": "2016-01-11T10:13:33.506Z",
- "artifacts_file": null,
- "finished_at": "2016-01-11T10:14:09.526Z",
- "id": 69,
- "name": "rubocop",
- "pipeline": {
- "id": 6,
- "ref": "master",
- "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "status": "pending"
- }
- "ref": "master",
- "runner": null,
- "stage": "test",
- "started_at": null,
- "status": "canceled",
- "tag": false,
- "user": null
- },
- {
- "commit": {
- "author_email": "admin@example.com",
- "author_name": "Administrator",
- "created_at": "2015-12-24T16:51:14.000+01:00",
- "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "message": "Test the CI integration.",
- "short_id": "0ff3ae19",
- "title": "Test the CI integration."
- },
- "coverage": null,
- "created_at": "2015-12-24T15:51:21.957Z",
- "artifacts_file": null,
- "finished_at": "2015-12-24T17:54:33.913Z",
- "id": 9,
- "name": "brakeman",
- "pipeline": {
- "id": 6,
- "ref": "master",
- "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "status": "pending"
- }
- "ref": "master",
- "runner": null,
- "stage": "test",
- "started_at": "2015-12-24T17:54:33.727Z",
- "status": "failed",
- "tag": false,
- "user": {
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "bio": null,
- "created_at": "2015-12-21T13:14:24.077Z",
- "id": 1,
- "is_admin": true,
- "linkedin": "",
- "name": "Administrator",
- "skype": "",
- "state": "active",
- "twitter": "",
- "username": "root",
- "web_url": "http://gitlab.dev/u/root",
- "website_url": ""
- }
- }
-]
-```
-
-## Get a single build
-
-Get a single build of a project
-
-```
-GET /projects/:id/builds/:build_id
-```
-
-| Attribute | Type | Required | Description |
-|------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
-| `build_id` | integer | yes | The ID of a build |
-
-```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/builds/8"
-```
-
-Example of response
-
-```json
-{
- "commit": {
- "author_email": "admin@example.com",
- "author_name": "Administrator",
- "created_at": "2015-12-24T16:51:14.000+01:00",
- "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "message": "Test the CI integration.",
- "short_id": "0ff3ae19",
- "title": "Test the CI integration."
- },
- "coverage": null,
- "created_at": "2015-12-24T15:51:21.880Z",
- "artifacts_file": null,
- "finished_at": "2015-12-24T17:54:31.198Z",
- "id": 8,
- "name": "rubocop",
- "pipeline": {
- "id": 6,
- "ref": "master",
- "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "status": "pending"
- }
- "ref": "master",
- "runner": null,
- "stage": "test",
- "started_at": "2015-12-24T17:54:30.733Z",
- "status": "failed",
- "tag": false,
- "user": {
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "bio": null,
- "created_at": "2015-12-21T13:14:24.077Z",
- "id": 1,
- "is_admin": true,
- "linkedin": "",
- "name": "Administrator",
- "skype": "",
- "state": "active",
- "twitter": "",
- "username": "root",
- "web_url": "http://gitlab.dev/u/root",
- "website_url": ""
- }
-}
-```
-
-## Get build artifacts
-
-> [Introduced][ce-2893] in GitLab 8.5
-
-Get build artifacts of a project
-
-```
-GET /projects/:id/builds/:build_id/artifacts
-```
-
-| Attribute | Type | Required | Description |
-|------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
-| `build_id` | integer | yes | The ID of a build |
-
-```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/builds/8/artifacts"
-```
-
-Response:
-
-| Status | Description |
-|-----------|---------------------------------|
-| 200 | Serves the artifacts file |
-| 404 | Build not found or no artifacts |
-
-[ce-2893]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2893
-
-## Download the artifacts file
-
-> [Introduced][ce-5347] in GitLab 8.10.
-
-Download the artifacts file from the given reference name and job provided the
-build finished successfully.
-
-```
-GET /projects/:id/builds/artifacts/:ref_name/download?job=name
-```
-
-Parameters
-
-| Attribute | Type | Required | Description |
-|-------------|---------|----------|-------------------------- |
-| `id` | integer | yes | The ID of a project |
-| `ref_name` | string | yes | The ref from a repository |
-| `job` | string | yes | The name of the job |
-
-Example request:
-
-```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/builds/artifacts/master/download?job=test"
-```
-
-Example response:
-
-| Status | Description |
-|-----------|---------------------------------|
-| 200 | Serves the artifacts file |
-| 404 | Build not found or no artifacts |
-
-[ce-5347]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5347
-
-## Get a trace file
-
-Get a trace of a specific build of a project
-
-```
-GET /projects/:id/builds/:build_id/trace
-```
-
-| Attribute | Type | Required | Description |
-|------------|---------|----------|---------------------|
-| id | integer | yes | The ID of a project |
-| build_id | integer | yes | The ID of a build |
-
-```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/builds/8/trace"
-```
-
-Response:
-
-| Status | Description |
-|-----------|-----------------------------------|
-| 200 | Serves the trace file |
-| 404 | Build not found or no trace file |
-
-## Cancel a build
-
-Cancel a single build of a project
-
-```
-POST /projects/:id/builds/:build_id/cancel
-```
-
-| Attribute | Type | Required | Description |
-|------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
-| `build_id` | integer | yes | The ID of a build |
-
-```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/builds/1/cancel"
-```
-
-Example of response
-
-```json
-{
- "commit": {
- "author_email": "admin@example.com",
- "author_name": "Administrator",
- "created_at": "2015-12-24T16:51:14.000+01:00",
- "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "message": "Test the CI integration.",
- "short_id": "0ff3ae19",
- "title": "Test the CI integration."
- },
- "coverage": null,
- "created_at": "2016-01-11T10:13:33.506Z",
- "artifacts_file": null,
- "finished_at": "2016-01-11T10:14:09.526Z",
- "id": 69,
- "name": "rubocop",
- "ref": "master",
- "runner": null,
- "stage": "test",
- "started_at": null,
- "status": "canceled",
- "tag": false,
- "user": null
-}
-```
-
-## Retry a build
-
-Retry a single build of a project
-
-```
-POST /projects/:id/builds/:build_id/retry
-```
-
-| Attribute | Type | Required | Description |
-|------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
-| `build_id` | integer | yes | The ID of a build |
-
-```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/builds/1/retry"
-```
-
-Example of response
-
-```json
-{
- "commit": {
- "author_email": "admin@example.com",
- "author_name": "Administrator",
- "created_at": "2015-12-24T16:51:14.000+01:00",
- "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "message": "Test the CI integration.",
- "short_id": "0ff3ae19",
- "title": "Test the CI integration."
- },
- "coverage": null,
- "created_at": "2016-01-11T10:13:33.506Z",
- "artifacts_file": null,
- "finished_at": null,
- "id": 69,
- "name": "rubocop",
- "ref": "master",
- "runner": null,
- "stage": "test",
- "started_at": null,
- "status": "pending",
- "tag": false,
- "user": null
-}
-```
-
-## Erase a build
-
-Erase a single build of a project (remove build artifacts and a build trace)
-
-```
-POST /projects/:id/builds/:build_id/erase
-```
-
-Parameters
-
-| Attribute | Type | Required | Description |
-|-------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
-| `build_id` | integer | yes | The ID of a build |
-
-Example of request
-
-```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/builds/1/erase"
-```
-
-Example of response
-
-```json
-{
- "commit": {
- "author_email": "admin@example.com",
- "author_name": "Administrator",
- "created_at": "2015-12-24T16:51:14.000+01:00",
- "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "message": "Test the CI integration.",
- "short_id": "0ff3ae19",
- "title": "Test the CI integration."
- },
- "coverage": null,
- "download_url": null,
- "id": 69,
- "name": "rubocop",
- "ref": "master",
- "runner": null,
- "stage": "test",
- "created_at": "2016-01-11T10:13:33.506Z",
- "started_at": "2016-01-11T10:13:33.506Z",
- "finished_at": "2016-01-11T10:15:10.506Z",
- "status": "failed",
- "tag": false,
- "user": null
-}
-```
-
-## Keep artifacts
-
-Prevents artifacts from being deleted when expiration is set.
-
-```
-POST /projects/:id/builds/:build_id/artifacts/keep
-```
-
-Parameters
-
-| Attribute | Type | Required | Description |
-|-------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
-| `build_id` | integer | yes | The ID of a build |
-
-Example request:
-
-```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/builds/1/artifacts/keep"
-```
-
-Example response:
-
-```json
-{
- "commit": {
- "author_email": "admin@example.com",
- "author_name": "Administrator",
- "created_at": "2015-12-24T16:51:14.000+01:00",
- "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "message": "Test the CI integration.",
- "short_id": "0ff3ae19",
- "title": "Test the CI integration."
- },
- "coverage": null,
- "download_url": null,
- "id": 69,
- "name": "rubocop",
- "ref": "master",
- "runner": null,
- "stage": "test",
- "created_at": "2016-01-11T10:13:33.506Z",
- "started_at": "2016-01-11T10:13:33.506Z",
- "finished_at": "2016-01-11T10:15:10.506Z",
- "status": "failed",
- "tag": false,
- "user": null
-}
-```
-
-## Play a build
-
-Triggers a manual action to start a build.
-
-```
-POST /projects/:id/builds/:build_id/play
-```
-
-| Attribute | Type | Required | Description |
-|------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
-| `build_id` | integer | yes | The ID of a build |
-
-```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/builds/1/play"
-```
-
-Example of response
-
-```json
-{
- "commit": {
- "author_email": "admin@example.com",
- "author_name": "Administrator",
- "created_at": "2015-12-24T16:51:14.000+01:00",
- "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "message": "Test the CI integration.",
- "short_id": "0ff3ae19",
- "title": "Test the CI integration."
- },
- "coverage": null,
- "created_at": "2016-01-11T10:13:33.506Z",
- "artifacts_file": null,
- "finished_at": null,
- "id": 69,
- "name": "rubocop",
- "ref": "master",
- "runner": null,
- "stage": "test",
- "started_at": null,
- "status": "started",
- "tag": false,
- "user": null
-}
-```
+This document was moved to [another location](jobs.md).
diff --git a/doc/api/ci/builds.md b/doc/api/ci/builds.md
index b6d79706a84..c8374d94716 100644
--- a/doc/api/ci/builds.md
+++ b/doc/api/ci/builds.md
@@ -5,7 +5,7 @@ API used by runners to receive and update builds.
>**Note:**
This API is intended to be used only by Runners as their own
communication channel. For the consumer API see the
-[Builds API](../builds.md).
+[Jobs API](../jobs.md).
## Authentication
diff --git a/doc/api/ci/lint.md b/doc/api/ci/lint.md
index 0c96b3ee335..6a4dca92cfe 100644
--- a/doc/api/ci/lint.md
+++ b/doc/api/ci/lint.md
@@ -1,4 +1,4 @@
-# Validate the .gitlab-ci.yml
+# Validate the .gitlab-ci.yml (API)
> [Introduced][ce-5953] in GitLab 8.12.
@@ -13,7 +13,7 @@ POST ci/lint
| `content` | string | yes | the .gitlab-ci.yaml content|
```bash
-curl --header "Content-Type: application/json" https://gitlab.example.com/api/v3/ci/lint --data '{"content": "{ \"image\": \"ruby:2.1\", \"services\": [\"postgres\"], \"before_script\": [\"gem install bundler\", \"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}'
+curl --header "Content-Type: application/json" https://gitlab.example.com/api/v4/ci/lint --data '{"content": "{ \"image\": \"ruby:2.1\", \"services\": [\"postgres\"], \"before_script\": [\"gem install bundler\", \"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}'
```
Be sure to copy paste the exact contents of `.gitlab-ci.yml` as YAML is very picky about indentation and spaces.
diff --git a/doc/api/ci/runners.md b/doc/api/ci/runners.md
index ecec53fde03..342c039dad8 100644
--- a/doc/api/ci/runners.md
+++ b/doc/api/ci/runners.md
@@ -1,4 +1,4 @@
-# Runners API
+# Register and Delete Runners API
API used by Runners to register and delete themselves.
@@ -12,7 +12,9 @@ communication channel. For the consumer API see the
This API uses two types of authentication:
1. Unique Runner's token, which is the token assigned to the Runner after it
- has been registered.
+ has been registered. This token can be found on the Runner's edit page (go to
+ **Project > Runners**, select one of the Runners listed under **Runners activated for
+ this project**).
2. Using Runners' registration token.
This is a token that can be found in project's settings.
@@ -48,7 +50,7 @@ DELETE /ci/api/v1/runners/delete
| Attribute | Type | Required | Description |
| --------- | ------- | --------- | ----------- |
-| `token` | string | yes | Runner's registration token |
+| `token` | string | yes | Unique Runner's token |
Example request:
diff --git a/doc/api/commits.md b/doc/api/commits.md
index 3e20beefb8a..c91f9ecbdaf 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -10,13 +10,13 @@ GET /projects/:id/repository/commits
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of a project or NAMESPACE/PROJECT_NAME owned by the authenticated user
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
| `ref_name` | string | no | The name of a repository branch or tag or if not given the default branch |
-| `since` | string | no | Only commits after or in this date will be returned in ISO 8601 format YYYY-MM-DDTHH:MM:SSZ |
-| `until` | string | no | Only commits before or in this date will be returned in ISO 8601 format YYYY-MM-DDTHH:MM:SSZ |
+| `since` | string | no | Only commits after or on this date will be returned in ISO 8601 format YYYY-MM-DDTHH:MM:SSZ |
+| `until` | string | no | Only commits before or on this date will be returned in ISO 8601 format YYYY-MM-DDTHH:MM:SSZ |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/repository/commits"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/commits"
```
Example response:
@@ -29,9 +29,15 @@ Example response:
"title": "Replace sanitize with escape once",
"author_name": "Dmitriy Zaporozhets",
"author_email": "dzaporozhets@sphereconsultinginc.com",
+ "authored_date": "2012-09-20T11:50:22+03:00",
+ "committer_name": "Administrator",
+ "committer_email": "admin@example.com",
+ "committed_date": "2012-09-20T11:50:22+03:00",
"created_at": "2012-09-20T11:50:22+03:00",
"message": "Replace sanitize with escape once",
- "allow_failure": false
+ "parent_ids": [
+ "6104942438c14ec7bd21c6cd5bd995272b3faff6"
+ ]
},
{
"id": "6104942438c14ec7bd21c6cd5bd995272b3faff6",
@@ -39,9 +45,13 @@ Example response:
"title": "Sanitize for network graph",
"author_name": "randx",
"author_email": "dmitriy.zaporozhets@gmail.com",
+ "committer_name": "Dmitriy",
+ "committer_email": "dmitriy.zaporozhets@gmail.com",
"created_at": "2012-09-20T09:06:12+03:00",
"message": "Sanitize for network graph",
- "allow_failure": false
+ "parent_ids": [
+ "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba"
+ ]
}
]
```
@@ -58,8 +68,8 @@ POST /projects/:id/repository/commits
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of a project or NAMESPACE/PROJECT_NAME |
-| `branch_name` | string | yes | The name of a branch |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `branch` | string | yes | The name of a branch |
| `commit_message` | string | yes | Commit message |
| `actions[]` | array | yes | An array of action hashes to commit as a batch. See the next table for what attributes it can take. |
| `author_email` | string | no | Specify the commit author's email address |
@@ -77,7 +87,7 @@ POST /projects/:id/repository/commits
```bash
PAYLOAD=$(cat << 'JSON'
{
- "branch_name": "master",
+ "branch": "master",
"commit_message": "some commit message",
"actions": [
{
@@ -87,7 +97,7 @@ PAYLOAD=$(cat << 'JSON'
},
{
"action": "delete",
- "file_path": "foo/bar2",
+ "file_path": "foo/bar2"
},
{
"action": "move",
@@ -104,7 +114,7 @@ PAYLOAD=$(cat << 'JSON'
}
JSON
)
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "Content-Type: application/json" --data "$PAYLOAD" https://gitlab.example.com/api/v3/projects/1/repository/commits
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "Content-Type: application/json" --data "$PAYLOAD" https://gitlab.example.com/api/v4/projects/1/repository/commits
```
Example response:
@@ -115,6 +125,8 @@ Example response:
"title": "some commit message",
"author_name": "Dmitriy Zaporozhets",
"author_email": "dzaporozhets@sphereconsultinginc.com",
+ "committer_name": "Dmitriy Zaporozhets",
+ "committer_email": "dzaporozhets@sphereconsultinginc.com",
"created_at": "2016-09-20T09:26:24.000-07:00",
"message": "some commit message",
"parent_ids": [
@@ -143,11 +155,11 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of a project or NAMESPACE/PROJECT_NAME owned by the authenticated user
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
| `sha` | string | yes | The commit hash or name of a repository branch or tag |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/repository/commits/master
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master
```
Example response:
@@ -159,6 +171,8 @@ Example response:
"title": "Sanitize for network graph",
"author_name": "randx",
"author_email": "dmitriy.zaporozhets@gmail.com",
+ "committer_name": "Dmitriy",
+ "committer_email": "dmitriy.zaporozhets@gmail.com",
"created_at": "2012-09-20T09:06:12+03:00",
"message": "Sanitize for network graph",
"committed_date": "2012-09-20T09:06:12+03:00",
@@ -175,6 +189,50 @@ Example response:
}
```
+## Cherry pick a commit
+
+> [Introduced][ce-8047] in GitLab 8.15.
+
+Cherry picks a commit to a given branch.
+
+```
+POST /projects/:id/repository/commits/:sha/cherry_pick
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+| `sha` | string | yes | The commit hash |
+| `branch` | string | yes | The name of the branch |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/cherry_pick"
+```
+
+Example response:
+
+```json
+{
+ "id": "8b090c1b79a14f2bd9e8a738f717824ff53aebad",
+ "short_id": "8b090c1b",
+ "title": "Feature added",
+ "author_name": "Dmitriy Zaporozhets",
+ "author_email": "dmitriy.zaporozhets@gmail.com",
+ "authored_date": "2016-12-12T20:10:39.000+01:00",
+ "created_at": "2016-12-12T20:10:39.000+01:00",
+ "committer_name": "Administrator",
+ "committer_email": "admin@example.com",
+ "committed_date": "2016-12-12T20:10:39.000+01:00",
+ "title": "Feature added",
+ "message": "Feature added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
+ "parent_ids": [
+ "a738f717824ff53aebad8b090c1b79a14f2bd9e8"
+ ]
+}
+```
+
## Get the diff of a commit
Get the diff of a commit in a project.
@@ -187,11 +245,11 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of a project or NAMESPACE/PROJECT_NAME owned by the authenticated user
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
| `sha` | string | yes | The commit hash or name of a repository branch or tag |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/repository/commits/master/diff"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/diff"
```
Example response:
@@ -199,7 +257,7 @@ Example response:
```json
[
{
- "diff": "--- a/doc/update/5.4-to-6.0.md\n+++ b/doc/update/5.4-to-6.0.md\n@@ -71,6 +71,8 @@\n sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production\n sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production\n \n+sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production\n+\n ```\n \n ### 6. Update config files",
+ "diff": "--- a/doc/update/5.4-to-6.0.md\n+++ b/doc/update/5.4-to-6.0.md\n@@ -71,6 +71,8 @@\n sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production\n sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production\n \n+sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production\n+\n ```\n \n ### 6. Update config files",
"new_path": "doc/update/5.4-to-6.0.md",
"old_path": "doc/update/5.4-to-6.0.md",
"a_mode": null,
@@ -223,11 +281,11 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of a project or NAMESPACE/PROJECT_NAME owned by the authenticated user
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
| `sha` | string | yes | The commit hash or name of a repository branch or tag |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/repository/commits/master/comments"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/comments"
```
Example response:
@@ -272,7 +330,7 @@ POST /projects/:id/repository/commits/:sha/comments
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of a project or NAMESPACE/PROJECT_NAME owned by the authenticated user
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
| `sha` | string | yes | The commit SHA or name of a repository branch or tag |
| `note` | string | yes | The text of the comment |
| `path` | string | no | The file path relative to the repository |
@@ -280,7 +338,7 @@ POST /projects/:id/repository/commits/:sha/comments
| `line_type` | string | no | The line type. Takes `new` or `old` as arguments |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "note=Nice picture man\!" --form "path=dudeism.md" --form "line=11" --form "line_type=new" https://gitlab.example.com/api/v3/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/comments
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "note=Nice picture man\!" --form "path=dudeism.md" --form "line=11" --form "line_type=new" https://gitlab.example.com/api/v4/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/comments
```
Example response:
@@ -288,7 +346,7 @@ Example response:
```json
{
"author" : {
- "web_url" : "https://gitlab.example.com/u/thedude",
+ "web_url" : "https://gitlab.example.com/thedude",
"avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png",
"username" : "thedude",
"state" : "active",
@@ -317,15 +375,15 @@ GET /projects/:id/repository/commits/:sha/statuses
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of a project or NAMESPACE/PROJECT_NAME owned by the authenticated user
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
| `sha` | string | yes | The commit SHA
-| `ref_name`| string | no | The name of a repository branch or tag or, if not given, the default branch
+| `ref` | string | no | The name of a repository branch or tag or, if not given, the default branch
| `stage` | string | no | Filter by [build stage](../ci/yaml/README.md#stages), e.g., `test`
| `name` | string | no | Filter by [job name](../ci/yaml/README.md#jobs), e.g., `bundler:audit`
| `all` | boolean | no | Return all statuses, not only the latest ones
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/statuses
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/17/repository/commits/18f3e63d05582537db6d183d9d557be09e1f90c8/statuses
```
Example response:
@@ -343,7 +401,7 @@ Example response:
"author" : {
"username" : "thedude",
"state" : "active",
- "web_url" : "https://gitlab.example.com/u/thedude",
+ "web_url" : "https://gitlab.example.com/thedude",
"avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png",
"id" : 28,
"name" : "Jeff Lebowski"
@@ -370,7 +428,7 @@ Example response:
"id" : 28,
"name" : "Jeff Lebowski",
"username" : "thedude",
- "web_url" : "https://gitlab.example.com/u/thedude",
+ "web_url" : "https://gitlab.example.com/thedude",
"state" : "active",
"avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png"
},
@@ -391,16 +449,17 @@ POST /projects/:id/statuses/:sha
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of a project or NAMESPACE/PROJECT_NAME owned by the authenticated user
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
| `sha` | string | yes | The commit SHA
| `state` | string | yes | The state of the status. Can be one of the following: `pending`, `running`, `success`, `failed`, `canceled`
| `ref` | string | no | The `ref` (branch or tag) to which the status refers
| `name` or `context` | string | no | The label to differentiate this status from the status of other systems. Default value is `default`
| `target_url` | string | no | The target URL to associate with this status
| `description` | string | no | The short description of the status
+| `coverage` | float | no | The total code coverage
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/17/statuses/18f3e63d05582537db6d183d9d557be09e1f90c8?state=success"
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/17/statuses/18f3e63d05582537db6d183d9d557be09e1f90c8?state=success"
```
Example response:
@@ -408,7 +467,7 @@ Example response:
```json
{
"author" : {
- "web_url" : "https://gitlab.example.com/u/thedude",
+ "web_url" : "https://gitlab.example.com/thedude",
"name" : "Jeff Lebowski",
"avatar_url" : "https://gitlab.example.com/uploads/user/avatar/28/The-Big-Lebowski-400-400.png",
"username" : "thedude",
@@ -418,6 +477,7 @@ Example response:
"name" : "default",
"sha" : "18f3e63d05582537db6d183d9d557be09e1f90c8",
"status" : "success",
+ "coverage": 100.0,
"description" : null,
"id" : 93,
"target_url" : null,
@@ -430,3 +490,4 @@ Example response:
```
[ce-6096]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6096 "Multi-file commit"
+[ce-8047]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8047
diff --git a/doc/api/deploy_key_multiple_projects.md b/doc/api/deploy_key_multiple_projects.md
index 73cb4b7ea8c..127f9a196de 100644
--- a/doc/api/deploy_key_multiple_projects.md
+++ b/doc/api/deploy_key_multiple_projects.md
@@ -1,4 +1,4 @@
-# Adding deploy keys to multiple projects
+# Adding deploy keys to multiple projects via API
If you want to easily add the same deploy key to multiple projects in the same
group, this can be achieved quite easily with the API.
@@ -7,16 +7,16 @@ First, find the ID of the projects you're interested in, by either listing all
projects:
```
-curl --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v3/projects
+curl --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v4/projects
```
Or finding the ID of a group and then listing all projects in that group:
```
-curl --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v3/groups
+curl --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v4/groups
# For group 1234:
-curl --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v3/groups/1234
+curl --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v4/groups/1234
```
With those IDs, add the same deploy key to all:
@@ -24,6 +24,6 @@ With those IDs, add the same deploy key to all:
```
for project_id in 321 456 987; do
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "Content-Type: application/json" \
- --data '{"title": "my key", "key": "ssh-rsa AAAA..."}' https://gitlab.example.com/api/v3/projects/${project_id}/deploy_keys
+ --data '{"title": "my key", "key": "ssh-rsa AAAA..."}' https://gitlab.example.com/api/v4/projects/${project_id}/deploy_keys
done
```
diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md
index ca44afbf355..4fa800ecb9c 100644
--- a/doc/api/deploy_keys.md
+++ b/doc/api/deploy_keys.md
@@ -1,15 +1,15 @@
-# Deploy Keys
+# Deploy Keys API
## List all deploy keys
-Get a list of all deploy keys across all projects.
+Get a list of all deploy keys across all projects of the GitLab instance. This endpoint requires admin access.
```
GET /deploy_keys
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/deploy_keys"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/deploy_keys"
```
Example response:
@@ -20,12 +20,14 @@ Example response:
"id": 1,
"title": "Public key",
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+ "can_push": false,
"created_at": "2013-10-02T10:12:29Z"
},
{
"id": 3,
"title": "Another Public key",
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+ "can_push": true,
"created_at": "2013-10-02T11:12:29Z"
}
]
@@ -41,10 +43,10 @@ GET /projects/:id/deploy_keys
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/deploy_keys"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/deploy_keys"
```
Example response:
@@ -55,12 +57,14 @@ Example response:
"id": 1,
"title": "Public key",
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+ "can_push": false,
"created_at": "2013-10-02T10:12:29Z"
},
{
"id": 3,
"title": "Another Public key",
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+ "can_push": false,
"created_at": "2013-10-02T11:12:29Z"
}
]
@@ -78,11 +82,11 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `key_id` | integer | yes | The ID of the deploy key |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/deploy_keys/11"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/deploy_keys/11"
```
Example response:
@@ -92,6 +96,7 @@ Example response:
"id": 1,
"title": "Public key",
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+ "can_push": false,
"created_at": "2013-10-02T10:12:29Z"
}
```
@@ -107,14 +112,15 @@ project only if original one was is accessible by the same user.
POST /projects/:id/deploy_keys
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of the project |
-| `title` | string | yes | New deploy key's title |
-| `key` | string | yes | New deploy key |
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `title` | string | yes | New deploy key's title |
+| `key` | string | yes | New deploy key |
+| `can_push` | boolean | no | Can deploy key push to the project's repository |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "Content-Type: application/json" --data '{"title": "My deploy key", "key": "ssh-rsa AAAA..."}' "https://gitlab.example.com/api/v3/projects/5/deploy_keys/"
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "Content-Type: application/json" --data '{"title": "My deploy key", "key": "ssh-rsa AAAA...", "can_push": "true"}' "https://gitlab.example.com/api/v4/projects/5/deploy_keys/"
```
Example response:
@@ -124,13 +130,14 @@ Example response:
"key" : "ssh-rsa AAAA...",
"id" : 12,
"title" : "My deploy key",
+ "can_push": true,
"created_at" : "2015-08-29T12:44:31.550Z"
}
```
## Delete deploy key
-Delete a deploy key from a project
+Removes a deploy key from the project. If the deploy key is used only for this project, it will be deleted from the system.
```
DELETE /projects/:id/deploy_keys/:key_id
@@ -138,26 +145,11 @@ DELETE /projects/:id/deploy_keys/:key_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `key_id` | integer | yes | The ID of the deploy key |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/deploy_keys/13"
-```
-
-Example response:
-
-```json
-{
- "updated_at" : "2015-08-29T12:50:57.259Z",
- "key" : "ssh-rsa AAAA...",
- "public" : false,
- "title" : "My deploy key",
- "user_id" : null,
- "created_at" : "2015-08-29T12:50:57.259Z",
- "fingerprint" : "6a:33:1f:74:51:c0:39:81:79:ec:7a:31:f8:40:20:43",
- "id" : 13
-}
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/deploy_keys/13"
```
## Enable a deploy key
@@ -165,36 +157,12 @@ Example response:
Enables a deploy key for a project so this can be used. Returns the enabled key, with a status code 201 when successful.
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/deploy_keys/13/enable
-```
-
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of the project |
-| `key_id` | integer | yes | The ID of the deploy key |
-
-Example response:
-
-```json
-{
- "key" : "ssh-rsa AAAA...",
- "id" : 12,
- "title" : "My deploy key",
- "created_at" : "2015-08-29T12:44:31.550Z"
-}
-```
-
-## Disable a deploy key
-
-Disable a deploy key for a project. Returns the disabled key.
-
-```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/deploy_keys/13/disable
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/deploy_keys/13/enable
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `key_id` | integer | yes | The ID of the deploy key |
Example response:
diff --git a/doc/api/deployments.md b/doc/api/deployments.md
index 417962de82d..ab9e63e01d3 100644
--- a/doc/api/deployments.md
+++ b/doc/api/deployments.md
@@ -10,10 +10,10 @@ GET /projects/:id/deployments
| Attribute | Type | Required | Description |
|-----------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/deployments"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/deployments"
```
Example of response
@@ -48,7 +48,6 @@ Example of response
"bio": null,
"created_at": "2016-08-11T07:09:20.351Z",
"id": 1,
- "is_admin": true,
"linkedin": "",
"location": null,
"name": "Administrator",
@@ -56,7 +55,7 @@ Example of response
"state": "active",
"twitter": "",
"username": "root",
- "web_url": "http://localhost:3000/u/root",
+ "web_url": "http://localhost:3000/root",
"website_url": ""
}
},
@@ -75,7 +74,7 @@ Example of response
"name": "Administrator",
"state": "active",
"username": "root",
- "web_url": "http://localhost:3000/u/root"
+ "web_url": "http://localhost:3000/root"
}
},
{
@@ -106,7 +105,6 @@ Example of response
"bio": null,
"created_at": "2016-08-11T07:09:20.351Z",
"id": 1,
- "is_admin": true,
"linkedin": "",
"location": null,
"name": "Administrator",
@@ -114,7 +112,7 @@ Example of response
"state": "active",
"twitter": "",
"username": "root",
- "web_url": "http://localhost:3000/u/root",
+ "web_url": "http://localhost:3000/root",
"website_url": ""
}
},
@@ -133,7 +131,7 @@ Example of response
"name": "Administrator",
"state": "active",
"username": "root",
- "web_url": "http://localhost:3000/u/root"
+ "web_url": "http://localhost:3000/root"
}
}
]
@@ -147,11 +145,11 @@ GET /projects/:id/deployments/:deployment_id
| Attribute | Type | Required | Description |
|-----------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `deployment_id` | integer | yes | The ID of the deployment |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/deployments/1"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/deployments/1"
```
Example of response
@@ -169,7 +167,7 @@ Example of response
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://localhost:3000/u/root"
+ "web_url": "http://localhost:3000/root"
},
"environment": {
"id": 9,
@@ -193,9 +191,8 @@ Example of response
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://localhost:3000/u/root",
+ "web_url": "http://localhost:3000/root",
"created_at": "2016-08-11T07:09:20.351Z",
- "is_admin": true,
"bio": null,
"location": null,
"skype": "",
diff --git a/doc/api/enviroments.md b/doc/api/environments.md
index 87a5fa67124..5ca766bf87d 100644
--- a/doc/api/enviroments.md
+++ b/doc/api/environments.md
@@ -1,4 +1,4 @@
-# Environments
+# Environments API
## List environments
@@ -10,10 +10,10 @@ GET /projects/:id/environments
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
-| `id` | integer | yes | The ID of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/1/environments
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/environments
```
Example response:
@@ -22,8 +22,9 @@ Example response:
[
{
"id": 1,
- "name": "Env1",
- "external_url": "https://env1.example.gitlab.com"
+ "name": "review/fix-foo",
+ "slug": "review-fix-foo-dfjre3",
+ "external_url": "https://review-fix-foo-dfjre3.example.gitlab.com"
}
]
```
@@ -32,7 +33,7 @@ Example response:
Creates a new environment with the given name and external_url.
-It returns 201 if the environment was successfully created, 400 for wrong parameters.
+It returns `201` if the environment was successfully created, `400` for wrong parameters.
```
POST /projects/:id/environment
@@ -40,12 +41,12 @@ POST /projects/:id/environment
| Attribute | Type | Required | Description |
| ------------- | ------- | -------- | ---------------------------- |
-| `id` | integer | yes | The ID of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `name` | string | yes | The name of the environment |
| `external_url` | string | no | Place to link to for this environment |
```bash
-curl --data "name=deploy&external_url=https://deploy.example.gitlab.com" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/environments"
+curl --data "name=deploy&external_url=https://deploy.example.gitlab.com" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/environments"
```
Example response:
@@ -54,6 +55,7 @@ Example response:
{
"id": 1,
"name": "deploy",
+ "slug": "deploy",
"external_url": "https://deploy.example.gitlab.com"
}
```
@@ -62,7 +64,7 @@ Example response:
Updates an existing environment's name and/or external_url.
-It returns 200 if the environment was successfully updated. In case of an error, a status code 400 is returned.
+It returns `200` if the environment was successfully updated. In case of an error, a status code `400` is returned.
```
PUT /projects/:id/environments/:environments_id
@@ -70,13 +72,13 @@ PUT /projects/:id/environments/:environments_id
| Attribute | Type | Required | Description |
| --------------- | ------- | --------------------------------- | ------------------------------- |
-| `id` | integer | yes | The ID of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `environment_id` | integer | yes | The ID of the environment | The ID of the environment |
| `name` | string | no | The new name of the environment |
| `external_url` | string | no | The new external_url |
```bash
-curl --request PUT --data "name=staging&external_url=https://staging.example.gitlab.com" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/environment/1"
+curl --request PUT --data "name=staging&external_url=https://staging.example.gitlab.com" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/environments/1"
```
Example response:
@@ -85,13 +87,14 @@ Example response:
{
"id": 1,
"name": "staging",
+ "slug": "staging",
"external_url": "https://staging.example.gitlab.com"
}
```
## Delete an environment
-It returns 200 if the environment was successfully deleted, and 404 if the environment does not exist.
+It returns `200` if the environment was successfully deleted, and `404` if the environment does not exist.
```
DELETE /projects/:id/environments/:environment_id
@@ -99,11 +102,28 @@ DELETE /projects/:id/environments/:environment_id
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
-| `id` | integer | yes | The ID of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `environment_id` | integer | yes | The ID of the environment |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/environment/1"
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/environments/1"
+```
+
+## Stop an environment
+
+It returns `200` if the environment was successfully stopped, and `404` if the environment does not exist.
+
+```
+POST /projects/:id/environments/:environment_id/stop
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------- | -------- | --------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `environment_id` | integer | yes | The ID of the environment |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/environments/1/stop"
```
Example response:
@@ -112,6 +132,7 @@ Example response:
{
"id": 1,
"name": "deploy",
+ "slug": "deploy",
"external_url": "https://deploy.example.gitlab.com"
}
```
diff --git a/doc/api/events.md b/doc/api/events.md
new file mode 100644
index 00000000000..e7829c9f479
--- /dev/null
+++ b/doc/api/events.md
@@ -0,0 +1,347 @@
+# Events
+
+## Filter parameters
+
+### Action Types
+
+Available action types for the `action` parameter are:
+
+- `created`
+- `updated`
+- `closed`
+- `reopened`
+- `pushed`
+- `commented`
+- `merged`
+- `joined`
+- `left`
+- `destroyed`
+- `expired`
+
+Note that these options are downcased.
+
+### Target Types
+
+Available target types for the `target_type` parameter are:
+
+- `issue`
+- `milestone`
+- `merge_request`
+- `note`
+- `project`
+- `snippet`
+- `user`
+
+Note that these options are downcased.
+
+### Date formatting
+
+Dates for the `before` and `after` parameters should be supplied in the following format:
+
+```
+YYYY-MM-DD
+```
+
+## List currently authenticated user's events
+
+>**Note:** This endpoint was introduced in GitLab 9.3.
+
+Get a list of events for the authenticated user.
+
+```
+GET /events
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `action` | string | no | Include only events of a particular [action type][action-types] |
+| `target_type` | string | no | Include only events of a particular [target type][target-types] |
+| `before` | date | no | Include only events created before a particular date. Please see [here for the supported format][date-formatting] |
+| `after` | date | no | Include only events created after a particular date. Please see [here for the supported format][date-formatting] |
+| `sort` | string | no | Sort events in `asc` or `desc` order by `created_at`. Default is `desc` |
+
+Example request:
+
+```
+curl --header "PRIVATE-TOKEN 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/events&target_type=issue&action=created&after=2017-01-31&before=2017-03-01
+```
+
+Example response:
+
+```json
+[
+ {
+ "title":null,
+ "project_id":1,
+ "action_name":"opened",
+ "target_id":160,
+ "target_type":"Issue",
+ "author_id":25,
+ "data":null,
+ "target_title":"Qui natus eos odio tempore et quaerat consequuntur ducimus cupiditate quis.",
+ "created_at":"2017-02-09T10:43:19.667Z",
+ "author":{
+ "name":"User 3",
+ "username":"user3",
+ "id":25,
+ "state":"active",
+ "avatar_url":"http://www.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?s=80\u0026d=identicon",
+ "web_url":"https://gitlab.example.com/user3"
+ },
+ "author_username":"user3"
+ },
+ {
+ "title":null,
+ "project_id":1,
+ "action_name":"opened",
+ "target_id":159,
+ "target_type":"Issue",
+ "author_id":21,
+ "data":null,
+ "target_title":"Nostrum enim non et sed optio illo deleniti non.",
+ "created_at":"2017-02-09T10:43:19.426Z",
+ "author":{
+ "name":"Test User",
+ "username":"ted",
+ "id":21,
+ "state":"active",
+ "avatar_url":"http://www.gravatar.com/avatar/80fb888c9a48b9a3f87477214acaa63f?s=80\u0026d=identicon",
+ "web_url":"https://gitlab.example.com/ted"
+ },
+ "author_username":"ted"
+ }
+]
+```
+
+### Get user contribution events
+
+>**Note:** Documentation was formerly located in the [Users API pages][users-api].
+
+Get the contribution events for the specified user, sorted from newest to oldest.
+
+```
+GET /users/:id/events
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer | yes | The ID or Username of the user |
+| `action` | string | no | Include only events of a particular [action type][action-types] |
+| `target_type` | string | no | Include only events of a particular [target type][target-types] |
+| `before` | date | no | Include only events created before a particular date. Please see [here for the supported format][date-formatting] |
+| `after` | date | no | Include only events created after a particular date. Please see [here for the supported format][date-formatting] |
+| `sort` | string | no | Sort events in `asc` or `desc` order by `created_at`. Default is `desc` |
+
+```bash
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/:id/events
+```
+
+Example response:
+
+```json
+[
+ {
+ "title": null,
+ "project_id": 15,
+ "action_name": "closed",
+ "target_id": 830,
+ "target_type": "Issue",
+ "author_id": 1,
+ "data": null,
+ "target_title": "Public project search field",
+ "author": {
+ "name": "Dmitriy Zaporozhets",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
+ "web_url": "http://localhost:3000/root"
+ },
+ "author_username": "root"
+ },
+ {
+ "title": null,
+ "project_id": 15,
+ "action_name": "opened",
+ "target_id": null,
+ "target_type": null,
+ "author_id": 1,
+ "author": {
+ "name": "Dmitriy Zaporozhets",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
+ "web_url": "http://localhost:3000/root"
+ },
+ "author_username": "john",
+ "data": {
+ "before": "50d4420237a9de7be1304607147aec22e4a14af7",
+ "after": "c5feabde2d8cd023215af4d2ceeb7a64839fc428",
+ "ref": "refs/heads/master",
+ "user_id": 1,
+ "user_name": "Dmitriy Zaporozhets",
+ "repository": {
+ "name": "gitlabhq",
+ "url": "git@dev.gitlab.org:gitlab/gitlabhq.git",
+ "description": "GitLab: self hosted Git management software. \r\nDistributed under the MIT License.",
+ "homepage": "https://dev.gitlab.org/gitlab/gitlabhq"
+ },
+ "commits": [
+ {
+ "id": "c5feabde2d8cd023215af4d2ceeb7a64839fc428",
+ "message": "Add simple search to projects in public area",
+ "timestamp": "2013-05-13T18:18:08+00:00",
+ "url": "https://dev.gitlab.org/gitlab/gitlabhq/commit/c5feabde2d8cd023215af4d2ceeb7a64839fc428",
+ "author": {
+ "name": "Dmitriy Zaporozhets",
+ "email": "dmitriy.zaporozhets@gmail.com"
+ }
+ }
+ ],
+ "total_commits_count": 1
+ },
+ "target_title": null
+ },
+ {
+ "title": null,
+ "project_id": 15,
+ "action_name": "closed",
+ "target_id": 840,
+ "target_type": "Issue",
+ "author_id": 1,
+ "data": null,
+ "target_title": "Finish & merge Code search PR",
+ "author": {
+ "name": "Dmitriy Zaporozhets",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
+ "web_url": "http://localhost:3000/root"
+ },
+ "author_username": "root"
+ },
+ {
+ "title": null,
+ "project_id": 15,
+ "action_name": "commented on",
+ "target_id": 1312,
+ "target_type": "Note",
+ "author_id": 1,
+ "data": null,
+ "target_title": null,
+ "created_at": "2015-12-04T10:33:58.089Z",
+ "note": {
+ "id": 1312,
+ "body": "What an awesome day!",
+ "attachment": null,
+ "author": {
+ "name": "Dmitriy Zaporozhets",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
+ "web_url": "http://localhost:3000/root"
+ },
+ "created_at": "2015-12-04T10:33:56.698Z",
+ "system": false,
+ "noteable_id": 377,
+ "noteable_type": "Issue"
+ },
+ "author": {
+ "name": "Dmitriy Zaporozhets",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
+ "web_url": "http://localhost:3000/root"
+ },
+ "author_username": "root"
+ }
+]
+```
+
+## List a Project's visible events
+
+>**Note:** This endpoint has been around longer than the others. Documentation was formerly located in the [Projects API pages][projects-api].
+
+Get a list of visible events for a particular project.
+
+```
+GET /:project_id/events
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `project_id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `action` | string | no | Include only events of a particular [action type][action-types] |
+| `target_type` | string | no | Include only events of a particular [target type][target-types] |
+| `before` | date | no | Include only events created before a particular date. Please see [here for the supported format][date-formatting] |
+| `after` | date | no | Include only events created after a particular date. Please see [here for the supported format][date-formatting] |
+| `sort` | string | no | Sort events in `asc` or `desc` order by `created_at`. Default is `desc` |
+
+Example request:
+
+```
+curl --header "PRIVATE-TOKEN 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:project_id/events&target_type=issue&action=created&after=2017-01-31&before=2017-03-01
+```
+
+Example response:
+
+```json
+[
+ {
+ "title":null,
+ "project_id":1,
+ "action_name":"opened",
+ "target_id":160,
+ "target_type":"Issue",
+ "author_id":25,
+ "data":null,
+ "target_title":"Qui natus eos odio tempore et quaerat consequuntur ducimus cupiditate quis.",
+ "created_at":"2017-02-09T10:43:19.667Z",
+ "author":{
+ "name":"User 3",
+ "username":"user3",
+ "id":25,
+ "state":"active",
+ "avatar_url":"http://www.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?s=80\u0026d=identicon",
+ "web_url":"https://gitlab.example.com/user3"
+ },
+ "author_username":"user3"
+ },
+ {
+ "title":null,
+ "project_id":1,
+ "action_name":"opened",
+ "target_id":159,
+ "target_type":"Issue",
+ "author_id":21,
+ "data":null,
+ "target_title":"Nostrum enim non et sed optio illo deleniti non.",
+ "created_at":"2017-02-09T10:43:19.426Z",
+ "author":{
+ "name":"Test User",
+ "username":"ted",
+ "id":21,
+ "state":"active",
+ "avatar_url":"http://www.gravatar.com/avatar/80fb888c9a48b9a3f87477214acaa63f?s=80\u0026d=identicon",
+ "web_url":"https://gitlab.example.com/ted"
+ },
+ "author_username":"ted"
+ }
+]
+```
+
+[target-types]: #target-types "Target Type parameter"
+[action-types]: #action-types "Action Type parameter"
+[date-formatting]: #date-formatting "Date Formatting guidance"
+[projects-api]: projects.md "Projects API pages"
+[users-api]: users.md "Users API pages"
diff --git a/doc/api/features.md b/doc/api/features.md
new file mode 100644
index 00000000000..89b8d3ac948
--- /dev/null
+++ b/doc/api/features.md
@@ -0,0 +1,83 @@
+# Features API
+
+All methods require administrator authorization.
+
+Notice that currently the API only supports boolean and percentage-of-time gate
+values.
+
+## List all features
+
+Get a list of all persisted features, with its gate values.
+
+```
+GET /features
+```
+
+```bash
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/features
+```
+
+Example response:
+
+```json
+[
+ {
+ "name": "experimental_feature",
+ "state": "off",
+ "gates": [
+ {
+ "key": "boolean",
+ "value": false
+ }
+ ]
+ },
+ {
+ "name": "new_library",
+ "state": "on",
+ "gates": [
+ {
+ "key": "boolean",
+ "value": true
+ }
+ ]
+ }
+]
+```
+
+## Set or create a feature
+
+Set a feature's gate value. If a feature with the given name doesn't exist yet
+it will be created. The value can be a boolean, or an integer to indicate
+percentage of time.
+
+```
+POST /features/:name
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `name` | string | yes | Name of the feature to create or update |
+| `value` | integer/string | yes | `true` or `false` to enable/disable, or an integer for percentage of time |
+
+```bash
+curl --data "value=30" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/features/new_library
+```
+
+Example response:
+
+```json
+{
+ "name": "new_library",
+ "state": "conditional",
+ "gates": [
+ {
+ "key": "boolean",
+ "value": false
+ },
+ {
+ "key": "percentage_of_time",
+ "value": 30
+ }
+ ]
+}
+```
diff --git a/doc/api/groups.md b/doc/api/groups.md
index e81d6f9de4b..2b3d8e125c8 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -1,8 +1,20 @@
-# Groups
+# Groups API
## List groups
-Get a list of groups. (As user: my groups, as admin: all groups)
+Get a list of groups. (As user: my groups or all available, as admin: all groups).
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `skip_groups` | array of integers | no | Skip the group IDs passes |
+| `all_available` | boolean | no | Show all the groups you have access to |
+| `search` | string | no | Return list of authorized groups matching the search criteria |
+| `order_by` | string | no | Order groups by `name` or `path`. Default is `name` |
+| `sort` | string | no | Order groups in `asc` or `desc` order. Default is `asc` |
+| `statistics` | boolean | no | Include group statistics (admins only) |
+| `owned` | boolean | no | Limit by groups owned by the current user |
```
GET /groups
@@ -14,14 +26,21 @@ GET /groups
"id": 1,
"name": "Foobar Group",
"path": "foo-bar",
- "description": "An interesting group"
+ "description": "An interesting group",
+ "visibility": "public",
+ "lfs_enabled": true,
+ "avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg",
+ "web_url": "http://localhost:3000/groups/foo-bar",
+ "request_access_enabled": false,
+ "full_name": "Foobar Group",
+ "full_path": "foo-bar",
+ "parent_id": null
}
]
```
You can search for groups by name or path, see below.
-
## List a group's projects
Get a list of projects in this group.
@@ -32,12 +51,19 @@ GET /groups/:id/projects
Parameters:
-- `archived` (optional) - if passed, limit by archived status
-- `visibility` (optional) - if passed, limit by visibility `public`, `internal`, `private`
-- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at`
-- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
-- `search` (optional) - Return list of authorized projects according to a search criteria
-- `ci_enabled_first` - Return projects ordered by ci_enabled flag. Projects with enabled GitLab CI go first
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `archived` | boolean | no | Limit by archived status |
+| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
+| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at` |
+| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
+| `search` | string | no | Return list of authorized projects matching the search criteria |
+| `simple` | boolean | no | Return only the ID, URL, name, and path of each project |
+| `owned` | boolean | no | Limit by projects owned by the current user |
+| `starred` | boolean | no | Limit by projects starred by the current user |
+
+Example response:
```json
[
@@ -46,9 +72,8 @@ Parameters:
"description": "foo",
"default_branch": "master",
"tag_list": [],
- "public": false,
"archived": false,
- "visibility_level": 10,
+ "visibility": "internal",
"ssh_url_to_repo": "git@gitlab.example.com/html5-boilerplate.git",
"http_url_to_repo": "http://gitlab.example.com/h5bp/html5-boilerplate.git",
"web_url": "http://gitlab.example.com/h5bp/html5-boilerplate",
@@ -59,7 +84,7 @@ Parameters:
"issues_enabled": true,
"merge_requests_enabled": true,
"wiki_enabled": true,
- "builds_enabled": true,
+ "jobs_enabled": true,
"snippets_enabled": true,
"created_at": "2016-04-05T21:40:50.169Z",
"last_activity_at": "2016-04-06T16:52:08.432Z",
@@ -69,21 +94,13 @@ Parameters:
"id": 5,
"name": "Experimental",
"path": "h5bp",
- "owner_id": null,
- "created_at": "2016-04-05T21:40:49.152Z",
- "updated_at": "2016-04-07T08:07:48.466Z",
- "description": "foo",
- "avatar": {
- "url": null
- },
- "share_with_group_lock": false,
- "visibility_level": 10
+ "kind": "group"
},
"avatar_url": null,
"star_count": 1,
"forks_count": 0,
"open_issues_count": 3,
- "public_builds": true,
+ "public_jobs": true,
"shared_with_groups": [],
"request_access_enabled": false
}
@@ -102,10 +119,10 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or path of a group |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/4
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/4
```
Example response:
@@ -116,19 +133,21 @@ Example response:
"name": "Twitter",
"path": "twitter",
"description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
- "visibility_level": 20,
+ "visibility": "public",
"avatar_url": null,
"web_url": "https://gitlab.example.com/groups/twitter",
"request_access_enabled": false,
+ "full_name": "Twitter",
+ "full_path": "twitter",
+ "parent_id": null,
"projects": [
{
"id": 7,
"description": "Voluptas veniam qui et beatae voluptas doloremque explicabo facilis.",
"default_branch": "master",
"tag_list": [],
- "public": true,
"archived": false,
- "visibility_level": 20,
+ "visibility": "public",
"ssh_url_to_repo": "git@gitlab.example.com:twitter/typeahead-js.git",
"http_url_to_repo": "https://gitlab.example.com/twitter/typeahead-js.git",
"web_url": "https://gitlab.example.com/twitter/typeahead-js",
@@ -139,7 +158,7 @@ Example response:
"issues_enabled": true,
"merge_requests_enabled": true,
"wiki_enabled": true,
- "builds_enabled": true,
+ "jobs_enabled": true,
"snippets_enabled": false,
"container_registry_enabled": true,
"created_at": "2016-06-17T07:47:25.578Z",
@@ -150,21 +169,13 @@ Example response:
"id": 4,
"name": "Twitter",
"path": "twitter",
- "owner_id": null,
- "created_at": "2016-06-17T07:47:24.216Z",
- "updated_at": "2016-06-17T07:47:24.216Z",
- "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
- "avatar": {
- "url": null
- },
- "share_with_group_lock": false,
- "visibility_level": 20
+ "kind": "group"
},
"avatar_url": null,
"star_count": 0,
"forks_count": 0,
"open_issues_count": 3,
- "public_builds": true,
+ "public_jobs": true,
"shared_with_groups": [],
"request_access_enabled": false
},
@@ -173,9 +184,8 @@ Example response:
"description": "Aspernatur omnis repudiandae qui voluptatibus eaque.",
"default_branch": "master",
"tag_list": [],
- "public": false,
"archived": false,
- "visibility_level": 10,
+ "visibility": "internal",
"ssh_url_to_repo": "git@gitlab.example.com:twitter/flight.git",
"http_url_to_repo": "https://gitlab.example.com/twitter/flight.git",
"web_url": "https://gitlab.example.com/twitter/flight",
@@ -186,7 +196,7 @@ Example response:
"issues_enabled": true,
"merge_requests_enabled": true,
"wiki_enabled": true,
- "builds_enabled": true,
+ "jobs_enabled": true,
"snippets_enabled": false,
"container_registry_enabled": true,
"created_at": "2016-06-17T07:47:24.661Z",
@@ -197,21 +207,13 @@ Example response:
"id": 4,
"name": "Twitter",
"path": "twitter",
- "owner_id": null,
- "created_at": "2016-06-17T07:47:24.216Z",
- "updated_at": "2016-06-17T07:47:24.216Z",
- "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
- "avatar": {
- "url": null
- },
- "share_with_group_lock": false,
- "visibility_level": 20
+ "kind": "group"
},
"avatar_url": null,
"star_count": 0,
"forks_count": 0,
"open_issues_count": 8,
- "public_builds": true,
+ "public_jobs": true,
"shared_with_groups": [],
"request_access_enabled": false
}
@@ -222,9 +224,8 @@ Example response:
"description": "Velit eveniet provident fugiat saepe eligendi autem.",
"default_branch": "master",
"tag_list": [],
- "public": false,
"archived": false,
- "visibility_level": 0,
+ "visibility": "private",
"ssh_url_to_repo": "git@gitlab.example.com:h5bp/html5-boilerplate.git",
"http_url_to_repo": "https://gitlab.example.com/h5bp/html5-boilerplate.git",
"web_url": "https://gitlab.example.com/h5bp/html5-boilerplate",
@@ -235,7 +236,7 @@ Example response:
"issues_enabled": true,
"merge_requests_enabled": true,
"wiki_enabled": true,
- "builds_enabled": true,
+ "jobs_enabled": true,
"snippets_enabled": false,
"container_registry_enabled": true,
"created_at": "2016-06-17T07:47:27.089Z",
@@ -246,21 +247,13 @@ Example response:
"id": 5,
"name": "H5bp",
"path": "h5bp",
- "owner_id": null,
- "created_at": "2016-06-17T07:47:26.621Z",
- "updated_at": "2016-06-17T07:47:26.621Z",
- "description": "Id consequatur rem vel qui doloremque saepe.",
- "avatar": {
- "url": null
- },
- "share_with_group_lock": false,
- "visibility_level": 20
+ "kind": "group"
},
"avatar_url": null,
"star_count": 0,
"forks_count": 0,
"open_issues_count": 4,
- "public_builds": true,
+ "public_jobs": true,
"shared_with_groups": [
{
"group_id": 4,
@@ -291,9 +284,10 @@ Parameters:
- `name` (required) - The name of the group
- `path` (required) - The path of the group
- `description` (optional) - The group's description
-- `visibility_level` (optional) - The group's visibility. 0 for private, 10 for internal, 20 for public.
+- `visibility` (optional) - The group's visibility. Can be `private`, `internal`, or `public`.
- `lfs_enabled` (optional) - Enable/disable Large File Storage (LFS) for the projects in this group
- `request_access_enabled` (optional) - Allow users to request member access.
+- `parent_id` (optional) - The parent group id for creating nested group.
## Transfer project to group
@@ -305,8 +299,8 @@ POST /groups/:id/projects/:project_id
Parameters:
-- `id` (required) - The ID or path of a group
-- `project_id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user
+- `project_id` (required) - The ID or path of a project
## Update group
@@ -322,12 +316,12 @@ PUT /groups/:id
| `name` | string | no | The name of the group |
| `path` | string | no | The path of the group |
| `description` | string | no | The description of the group |
-| `visibility_level` | integer | no | The visibility level of the group. 0 for private, 10 for internal, 20 for public. |
+| `visibility` | string | no | The visibility level of the group. Can be `private`, `internal`, or `public`. |
| `lfs_enabled` (optional) | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group |
| `request_access_enabled` | boolean | no | Allow users to request member access. |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/groups/5?name=Experimental"
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/5?name=Experimental"
```
@@ -339,10 +333,13 @@ Example response:
"name": "Experimental",
"path": "h5bp",
"description": "foo",
- "visibility_level": 10,
+ "visibility": "internal",
"avatar_url": null,
"web_url": "http://gitlab.example.com/groups/h5bp",
"request_access_enabled": false,
+ "full_name": "Foobar Group",
+ "full_path": "foo-bar",
+ "parent_id": null,
"projects": [
{
"id": 9,
@@ -351,7 +348,7 @@ Example response:
"tag_list": [],
"public": false,
"archived": false,
- "visibility_level": 10,
+ "visibility": "internal",
"ssh_url_to_repo": "git@gitlab.example.com/html5-boilerplate.git",
"http_url_to_repo": "http://gitlab.example.com/h5bp/html5-boilerplate.git",
"web_url": "http://gitlab.example.com/h5bp/html5-boilerplate",
@@ -362,7 +359,7 @@ Example response:
"issues_enabled": true,
"merge_requests_enabled": true,
"wiki_enabled": true,
- "builds_enabled": true,
+ "jobs_enabled": true,
"snippets_enabled": true,
"created_at": "2016-04-05T21:40:50.169Z",
"last_activity_at": "2016-04-06T16:52:08.432Z",
@@ -372,21 +369,13 @@ Example response:
"id": 5,
"name": "Experimental",
"path": "h5bp",
- "owner_id": null,
- "created_at": "2016-04-05T21:40:49.152Z",
- "updated_at": "2016-04-07T08:07:48.466Z",
- "description": "foo",
- "avatar": {
- "url": null
- },
- "share_with_group_lock": false,
- "visibility_level": 10
+ "kind": "group"
},
"avatar_url": null,
"star_count": 1,
"forks_count": 0,
"open_issues_count": 3,
- "public_builds": true,
+ "public_jobs": true,
"shared_with_groups": [],
"request_access_enabled": false
}
diff --git a/doc/api/issues.md b/doc/api/issues.md
index eed0d2fce51..df5666bb7b6 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -1,4 +1,4 @@
-# Issues
+# Issues API
Every API call to issues must be authenticated.
@@ -23,17 +23,24 @@ GET /issues?state=closed
GET /issues?labels=foo
GET /issues?labels=foo,bar
GET /issues?labels=foo,bar&state=opened
-```
-
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `state` | string | no | Return all issues or just those that are `opened` or `closed`|
-| `labels` | string | no | Comma-separated list of label names, issues with any of the labels will be returned |
-| `order_by`| string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
-| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` |
+GET /issues?milestone=1.0.0
+GET /issues?milestone=1.0.0&state=opened
+GET /issues?iids[]=42&iids[]=43
+GET /issues?search=issue+title+or+description
+```
+
+| Attribute | Type | Required | Description |
+|-------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------------------|
+| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
+| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `No+Label` lists all issues with no labels |
+| `milestone` | string | no | The milestone title |
+| `iids` | Array[integer] | no | Return only the issues having the given `iid` |
+| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
+| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` |
+| `search` | string | no | Search issues against their `title` and `description` |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/issues
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/issues
```
Example response:
@@ -46,7 +53,7 @@ Example response:
"author" : {
"state" : "active",
"id" : 18,
- "web_url" : "https://gitlab.example.com/u/eileen.lowe",
+ "web_url" : "https://gitlab.example.com/eileen.lowe",
"name" : "Alexandra Bashirian",
"avatar_url" : null,
"username" : "eileen.lowe"
@@ -63,11 +70,19 @@ Example response:
"updated_at" : "2016-01-04T15:31:39.996Z"
},
"project_id" : 1,
+ "assignees" : [{
+ "state" : "active",
+ "id" : 1,
+ "name" : "Administrator",
+ "web_url" : "https://gitlab.example.com/root",
+ "avatar_url" : null,
+ "username" : "root"
+ }],
"assignee" : {
"state" : "active",
"id" : 1,
"name" : "Administrator",
- "web_url" : "https://gitlab.example.com/u/root",
+ "web_url" : "https://gitlab.example.com/root",
"avatar_url" : null,
"username" : "root"
},
@@ -77,7 +92,6 @@ Example response:
"created_at" : "2016-01-04T15:31:51.081Z",
"iid" : 6,
"labels" : [],
- "subscribed" : false,
"user_notes_count": 1,
"due_date": "2016-07-22",
"web_url": "http://example.com/example/example/issues/6",
@@ -86,6 +100,8 @@ Example response:
]
```
+**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+
## List group issues
Get a list of a group's issues.
@@ -99,20 +115,24 @@ GET /groups/:id/issues?labels=foo,bar
GET /groups/:id/issues?labels=foo,bar&state=opened
GET /groups/:id/issues?milestone=1.0.0
GET /groups/:id/issues?milestone=1.0.0&state=opened
+GET /groups/:id/issues?iids[]=42&iids[]=43
+GET /groups/:id/issues?search=issue+title+or+description
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a group |
-| `state` | string | no | Return all issues or just those that are `opened` or `closed`|
-| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned |
-| `milestone` | string| no | The milestone title |
-| `order_by`| string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
-| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` |
+| Attribute | Type | Required | Description |
+|-------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
+| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `No+Label` lists all issues with no labels |
+| `iids` | Array[integer] | no | Return only the issues having the given `iid` |
+| `milestone` | string | no | The milestone title |
+| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
+| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` |
+| `search` | string | no | Search group issues against their `title` and `description` |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/4/issues
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/4/issues
```
Example response:
@@ -134,7 +154,7 @@ Example response:
},
"author" : {
"state" : "active",
- "web_url" : "https://gitlab.example.com/u/root",
+ "web_url" : "https://gitlab.example.com/root",
"avatar_url" : null,
"username" : "root",
"id" : 1,
@@ -143,9 +163,17 @@ Example response:
"description" : "Omnis vero earum sunt corporis dolor et placeat.",
"state" : "closed",
"iid" : 1,
+ "assignees" : [{
+ "avatar_url" : null,
+ "web_url" : "https://gitlab.example.com/lennie",
+ "state" : "active",
+ "username" : "lennie",
+ "id" : 9,
+ "name" : "Dr. Luella Kovacek"
+ }],
"assignee" : {
"avatar_url" : null,
- "web_url" : "https://gitlab.example.com/u/lennie",
+ "web_url" : "https://gitlab.example.com/lennie",
"state" : "active",
"username" : "lennie",
"id" : 9,
@@ -156,7 +184,6 @@ Example response:
"title" : "Ut commodi ullam eos dolores perferendis nihil sunt.",
"updated_at" : "2016-01-04T15:31:46.176Z",
"created_at" : "2016-01-04T15:31:46.176Z",
- "subscribed" : false,
"user_notes_count": 1,
"due_date": null,
"web_url": "http://example.com/example/example/issues/1",
@@ -165,6 +192,8 @@ Example response:
]
```
+**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+
## List project issues
Get a list of a project's issues.
@@ -178,22 +207,25 @@ GET /projects/:id/issues?labels=foo,bar
GET /projects/:id/issues?labels=foo,bar&state=opened
GET /projects/:id/issues?milestone=1.0.0
GET /projects/:id/issues?milestone=1.0.0&state=opened
-GET /projects/:id/issues?iid=42
-```
-
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `iid` | integer | no | Return the issue having the given `iid` |
-| `state` | string | no | Return all issues or just those that are `opened` or `closed`|
-| `labels` | string | no | Comma-separated list of label names, issues with any of the labels will be returned |
-| `milestone` | string| no | The milestone title |
-| `order_by`| string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
-| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` |
-
+GET /projects/:id/issues?iids[]=42&iids[]=43
+GET /projects/:id/issues?search=issue+title+or+description
+```
+
+| Attribute | Type | Required | Description |
+|-------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `iids` | Array[integer] | no | Return only the milestone having the given `iid` |
+| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
+| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `No+Label` lists all issues with no labels |
+| `milestone` | string | no | The milestone title |
+| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
+| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` |
+| `search` | string | no | Search project issues against their `title` and `description` |
+| `created_after` | datetime | no | Return issues created after the given time (inclusive) |
+| `created_before` | datetime | no | Return issues created before the given time (inclusive) |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/4/issues
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/issues
```
Example response:
@@ -215,7 +247,7 @@ Example response:
},
"author" : {
"state" : "active",
- "web_url" : "https://gitlab.example.com/u/root",
+ "web_url" : "https://gitlab.example.com/root",
"avatar_url" : null,
"username" : "root",
"id" : 1,
@@ -224,9 +256,17 @@ Example response:
"description" : "Omnis vero earum sunt corporis dolor et placeat.",
"state" : "closed",
"iid" : 1,
+ "assignees" : [{
+ "avatar_url" : null,
+ "web_url" : "https://gitlab.example.com/lennie",
+ "state" : "active",
+ "username" : "lennie",
+ "id" : 9,
+ "name" : "Dr. Luella Kovacek"
+ }],
"assignee" : {
"avatar_url" : null,
- "web_url" : "https://gitlab.example.com/u/lennie",
+ "web_url" : "https://gitlab.example.com/lennie",
"state" : "active",
"username" : "lennie",
"id" : 9,
@@ -237,7 +277,6 @@ Example response:
"title" : "Ut commodi ullam eos dolores perferendis nihil sunt.",
"updated_at" : "2016-01-04T15:31:46.176Z",
"created_at" : "2016-01-04T15:31:46.176Z",
- "subscribed" : false,
"user_notes_count": 1,
"due_date": "2016-07-22",
"web_url": "http://example.com/example/example/issues/1",
@@ -246,21 +285,23 @@ Example response:
]
```
+**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+
## Single issue
Get a single project issue.
```
-GET /projects/:id/issues/:issue_id
+GET /projects/:id/issues/:issue_iid
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `issue_id`| integer | yes | The ID of a project's issue |
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/4/issues/41
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/issues/41
```
Example response:
@@ -281,7 +322,7 @@ Example response:
},
"author" : {
"state" : "active",
- "web_url" : "https://gitlab.example.com/u/root",
+ "web_url" : "https://gitlab.example.com/root",
"avatar_url" : null,
"username" : "root",
"id" : 1,
@@ -290,9 +331,17 @@ Example response:
"description" : "Omnis vero earum sunt corporis dolor et placeat.",
"state" : "closed",
"iid" : 1,
+ "assignees" : [{
+ "avatar_url" : null,
+ "web_url" : "https://gitlab.example.com/lennie",
+ "state" : "active",
+ "username" : "lennie",
+ "id" : 9,
+ "name" : "Dr. Luella Kovacek"
+ }],
"assignee" : {
"avatar_url" : null,
- "web_url" : "https://gitlab.example.com/u/lennie",
+ "web_url" : "https://gitlab.example.com/lennie",
"state" : "active",
"username" : "lennie",
"id" : 9,
@@ -311,32 +360,32 @@ Example response:
}
```
+**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+
## New issue
Creates a new project issue.
-If the operation is successful, a status code of `200` and the newly-created
-issue is returned. If an error occurs, an error number and a message explaining
-the reason is returned.
-
```
POST /projects/:id/issues
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `title` | string | yes | The title of an issue |
-| `description` | string | no | The description of an issue |
-| `confidential` | boolean | no | Set an issue to be confidential. Default is `false`. |
-| `assignee_id` | integer | no | The ID of a user to assign issue |
-| `milestone_id` | integer | no | The ID of a milestone to assign issue |
-| `labels` | string | no | Comma-separated label names for an issue |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. `2016-03-11T03:45:40Z` (requires admin or project owner rights) |
-| `due_date` | string | no | Date time string in the format YEAR-MONTH-DAY, e.g. `2016-03-11` |
+| Attribute | Type | Required | Description |
+|-------------------------------------------|----------------|----------|--------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `title` | string | yes | The title of an issue |
+| `description` | string | no | The description of an issue |
+| `confidential` | boolean | no | Set an issue to be confidential. Default is `false`. |
+| `assignee_ids` | Array[integer] | no | The ID of the users to assign issue |
+| `milestone_id` | integer | no | The ID of a milestone to assign issue |
+| `labels` | string | no | Comma-separated label names for an issue |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. `2016-03-11T03:45:40Z` (requires admin or project owner rights) |
+| `due_date` | string | no | Date time string in the format YEAR-MONTH-DAY, e.g. `2016-03-11` |
+| `merge_request_to_resolve_discussions_of` | integer | no | The IID of a merge request in which to resolve all issues. This will fill the issue with a default description and mark all discussions as resolved. When passing a description or title, these values will take precedence over the default values.|
+| `discussion_to_resolve` | string | no | The ID of a discussion to resolve. This will fill in the issue with a default description and mark the discussion as resolved. Use in combination with `merge_request_to_resolve_discussions_of`. |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/4/issues?title=Issues%20with%20auth&labels=bug
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/issues?title=Issues%20with%20auth&labels=bug
```
Example response:
@@ -349,6 +398,7 @@ Example response:
"iid" : 14,
"title" : "Issues with auth",
"state" : "opened",
+ "assignees" : [],
"assignee" : null,
"labels" : [
"bug"
@@ -357,7 +407,7 @@ Example response:
"name" : "Alexandra Bashirian",
"avatar_url" : null,
"state" : "active",
- "web_url" : "https://gitlab.example.com/u/eileen.lowe",
+ "web_url" : "https://gitlab.example.com/eileen.lowe",
"id" : 18,
"username" : "eileen.lowe"
},
@@ -372,35 +422,33 @@ Example response:
}
```
+**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+
## Edit issue
Updates an existing project issue. This call is also used to mark an issue as
closed.
-If the operation is successful, a code of `200` and the updated issue is
-returned. If an error occurs, an error number and a message explaining the
-reason is returned.
-
```
-PUT /projects/:id/issues/:issue_id
+PUT /projects/:id/issues/:issue_iid
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `issue_id` | integer | yes | The ID of a project's issue |
-| `title` | string | no | The title of an issue |
-| `description` | string | no | The description of an issue |
-| `confidential` | boolean | no | Updates an issue to be confidential |
-| `assignee_id` | integer | no | The ID of a user to assign the issue to |
-| `milestone_id` | integer | no | The ID of a milestone to assign the issue to |
-| `labels` | string | no | Comma-separated label names for an issue |
-| `state_event` | string | no | The state event of an issue. Set `close` to close the issue and `reopen` to reopen it |
-| `updated_at` | string | no | Date time string, ISO 8601 formatted, e.g. `2016-03-11T03:45:40Z` (requires admin or project owner rights) |
-| `due_date` | string | no | Date time string in the format YEAR-MONTH-DAY, e.g. `2016-03-11` |
+| Attribute | Type | Required | Description |
+|----------------|---------|----------|------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
+| `title` | string | no | The title of an issue |
+| `description` | string | no | The description of an issue |
+| `confidential` | boolean | no | Updates an issue to be confidential |
+| `assignee_ids` | Array[integer] | no | The ID of the users to assign the issue to |
+| `milestone_id` | integer | no | The ID of a milestone to assign the issue to |
+| `labels` | string | no | Comma-separated label names for an issue |
+| `state_event` | string | no | The state event of an issue. Set `close` to close the issue and `reopen` to reopen it |
+| `updated_at` | string | no | Date time string, ISO 8601 formatted, e.g. `2016-03-11T03:45:40Z` (requires admin or project owner rights) |
+| `due_date` | string | no | Date time string in the format YEAR-MONTH-DAY, e.g. `2016-03-11` |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/4/issues/85?state_event=close
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/issues/85?state_event=close
```
Example response:
@@ -414,7 +462,7 @@ Example response:
"username" : "eileen.lowe",
"id" : 18,
"state" : "active",
- "web_url" : "https://gitlab.example.com/u/eileen.lowe"
+ "web_url" : "https://gitlab.example.com/eileen.lowe"
},
"state" : "closed",
"title" : "Issues with auth",
@@ -426,6 +474,7 @@ Example response:
"bug"
],
"id" : 85,
+ "assignees" : [],
"assignee" : null,
"milestone" : null,
"subscribed" : true,
@@ -436,30 +485,28 @@ Example response:
}
```
+**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+
## Delete an issue
Only for admins and project owners. Soft deletes the issue in question.
-If the operation is successful, a status code `200` is returned. In case you cannot
-destroy this issue, or it is not present, code `404` is given.
```
-DELETE /projects/:id/issues/:issue_id
+DELETE /projects/:id/issues/:issue_iid
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `issue_id` | integer | yes | The ID of a project's issue |
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/4/issues/85
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/issues/85
```
## Move an issue
-Moves an issue to a different project. If the operation is successful, a status
-code `201` together with moved issue is returned. If the project, issue, or
-target project is not found, error `404` is returned. If the target project
+Moves an issue to a different project. If the target project
equals the source project or the user has insufficient permissions to move an
issue, error `400` together with an explaining error message is returned.
@@ -467,17 +514,17 @@ If a given label and/or milestone with the same name also exists in the target
project, it will then be assigned to the issue that is being moved.
```
-POST /projects/:id/issues/:issue_id/move
+POST /projects/:id/issues/:issue_iid/move
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `issue_id` | integer | yes | The ID of a project's issue |
-| `to_project_id` | integer | yes | The ID of the new project |
+| Attribute | Type | Required | Description |
+|-----------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
+| `to_project_id` | integer | yes | The ID of the new project |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/4/issues/85/move
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/issues/85/move
```
Example response:
@@ -494,13 +541,21 @@ Example response:
"updated_at": "2016-04-07T12:20:17.596Z",
"labels": [],
"milestone": null,
+ "assignees": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"assignee": {
"name": "Miss Monserrate Beier",
"username": "axel.block",
"id": 12,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/axel.block"
+ "web_url": "https://gitlab.example.com/axel.block"
},
"author": {
"name": "Kris Steuber",
@@ -508,7 +563,7 @@ Example response:
"id": 10,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/7a190fecbaa68212a4b68aeb6e3acd10?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/solon.cremin"
+ "web_url": "https://gitlab.example.com/solon.cremin"
},
"due_date": null,
"web_url": "http://example.com/example/example/issues/11",
@@ -516,25 +571,25 @@ Example response:
}
```
+**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+
## Subscribe to an issue
-Subscribes the authenticated user to an issue to receive notifications. If the
-operation is successful, status code `201` together with the updated issue is
-returned. If the user is already subscribed to the issue, the status code `304`
-is returned. If the project or issue is not found, status code `404` is
-returned.
+Subscribes the authenticated user to an issue to receive notifications.
+If the user is already subscribed to the issue, the status code `304`
+is returned.
```
-POST /projects/:id/issues/:issue_id/subscription
+POST /projects/:id/issues/:issue_iid/subscribe
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `issue_id` | integer | yes | The ID of a project's issue |
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/issues/93/subscription
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/subscribe
```
Example response:
@@ -551,13 +606,21 @@ Example response:
"updated_at": "2016-04-07T12:20:17.596Z",
"labels": [],
"milestone": null,
+ "assignees": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"assignee": {
"name": "Miss Monserrate Beier",
"username": "axel.block",
"id": 12,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/axel.block"
+ "web_url": "https://gitlab.example.com/axel.block"
},
"author": {
"name": "Kris Steuber",
@@ -565,7 +628,7 @@ Example response:
"id": 10,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/7a190fecbaa68212a4b68aeb6e3acd10?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/solon.cremin"
+ "web_url": "https://gitlab.example.com/solon.cremin"
},
"due_date": null,
"web_url": "http://example.com/example/example/issues/11",
@@ -573,82 +636,44 @@ Example response:
}
```
+**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+
## Unsubscribe from an issue
Unsubscribes the authenticated user from the issue to not receive notifications
-from it. If the operation is successful, status code `200` together with the
-updated issue is returned. If the user is not subscribed to the issue, the
-status code `304` is returned. If the project or issue is not found, status code
-`404` is returned.
+from it. If the user is not subscribed to the issue, the
+status code `304` is returned.
```
-DELETE /projects/:id/issues/:issue_id/subscription
+POST /projects/:id/issues/:issue_iid/unsubscribe
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `issue_id` | integer | yes | The ID of a project's issue |
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/issues/93/subscription
-```
-
-Example response:
-
-```json
-{
- "id": 93,
- "iid": 12,
- "project_id": 5,
- "title": "Incidunt et rerum ea expedita iure quibusdam.",
- "description": "Et cumque architecto sed aut ipsam.",
- "state": "opened",
- "created_at": "2016-04-05T21:41:45.217Z",
- "updated_at": "2016-04-07T13:02:37.905Z",
- "labels": [],
- "milestone": null,
- "assignee": {
- "name": "Edwardo Grady",
- "username": "keyon",
- "id": 21,
- "state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/3e6f06a86cf27fa8b56f3f74f7615987?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/keyon"
- },
- "author": {
- "name": "Vivian Hermann",
- "username": "orville",
- "id": 11,
- "state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/5224fd70153710e92fb8bcf79ac29d67?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/orville"
- },
- "subscribed": false,
- "due_date": null,
- "web_url": "http://example.com/example/example/issues/12",
- "confidential": false
-}
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/unsubscribe
```
## Create a todo
-Manually creates a todo for the current user on an issue. If the request is
-successful, status code `200` together with the created todo is returned. If
+Manually creates a todo for the current user on an issue. If
there already exists a todo for the user on that issue, status code `304` is
returned.
```
-POST /projects/:id/issues/:issue_id/todo
+POST /projects/:id/issues/:issue_iid/todo
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `issue_id` | integer | yes | The ID of a project's issue |
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/issues/93/todo
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/todo
```
Example response:
@@ -669,7 +694,7 @@ Example response:
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/root"
+ "web_url": "https://gitlab.example.com/root"
},
"action_name": "marked",
"target_type": "Issue",
@@ -694,13 +719,21 @@ Example response:
"updated_at": "2016-06-17T07:47:33.832Z",
"due_date": null
},
+ "assignees": [{
+ "name": "Jarret O'Keefe",
+ "username": "francisca",
+ "id": 14,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/a7fa515d53450023c83d62986d0658a8?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/francisca"
+ }],
"assignee": {
"name": "Jarret O'Keefe",
"username": "francisca",
"id": 14,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/a7fa515d53450023c83d62986d0658a8?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/francisca"
+ "web_url": "https://gitlab.example.com/francisca"
},
"author": {
"name": "Maxie Medhurst",
@@ -708,7 +741,7 @@ Example response:
"id": 12,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/craig_rutherford"
+ "web_url": "https://gitlab.example.com/craig_rutherford"
},
"subscribed": true,
"user_notes_count": 7,
@@ -725,6 +758,209 @@ Example response:
}
```
+**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+
+## Set a time estimate for an issue
+
+Sets an estimated time of work for this issue.
+
+```
+POST /projects/:id/issues/:issue_iid/time_estimate
+```
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
+| `duration` | string | yes | The duration in human format. e.g: 3h30m |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/time_estimate?duration=3h30m
+```
+
+Example response:
+
+```json
+{
+ "human_time_estimate": "3h 30m",
+ "human_total_time_spent": null,
+ "time_estimate": 12600,
+ "total_time_spent": 0
+}
+```
+
+## Reset the time estimate for an issue
+
+Resets the estimated time for this issue to 0 seconds.
+
+```
+POST /projects/:id/issues/:issue_iid/reset_time_estimate
+```
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/reset_time_estimate
+```
+
+Example response:
+
+```json
+{
+ "human_time_estimate": null,
+ "human_total_time_spent": null,
+ "time_estimate": 0,
+ "total_time_spent": 0
+}
+```
+
+## Add spent time for an issue
+
+Adds spent time for this issue
+
+```
+POST /projects/:id/issues/:issue_iid/add_spent_time
+```
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
+| `duration` | string | yes | The duration in human format. e.g: 3h30m |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/add_spent_time?duration=1h
+```
+
+Example response:
+
+```json
+{
+ "human_time_estimate": null,
+ "human_total_time_spent": "1h",
+ "time_estimate": 0,
+ "total_time_spent": 3600
+}
+```
+
+## Reset spent time for an issue
+
+Resets the total spent time for this issue to 0 seconds.
+
+```
+POST /projects/:id/issues/:issue_iid/reset_spent_time
+```
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/reset_spent_time
+```
+
+Example response:
+
+```json
+{
+ "human_time_estimate": null,
+ "human_total_time_spent": null,
+ "time_estimate": 0,
+ "total_time_spent": 0
+}
+```
+
+## Get time tracking stats
+
+```
+GET /projects/:id/issues/:issue_iid/time_stats
+```
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/93/time_stats
+```
+
+Example response:
+
+```json
+{
+ "human_time_estimate": "2h",
+ "human_total_time_spent": "1h",
+ "time_estimate": 7200,
+ "total_time_spent": 3600
+}
+```
+
+## List merge requests that will close issue on merge
+
+Get all the merge requests that will close issue when merged.
+
+```
+GET /projects/:id/issues/:issue_iid/closed_by
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer | yes | The ID of a project |
+| `issue_iid` | integer | yes | The internal ID of a project issue |
+
+```bash
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/11/closed_by
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 6471,
+ "iid": 6432,
+ "project_id": 1,
+ "title": "add a test for cgi lexer options",
+ "description": "closes #11",
+ "state": "opened",
+ "created_at": "2017-04-06T18:33:34.168Z",
+ "updated_at": "2017-04-09T20:10:24.983Z",
+ "target_branch": "master",
+ "source_branch": "feature.custom-highlighting",
+ "upvotes": 0,
+ "downvotes": 0,
+ "author": {
+ "name": "Administrator",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/root"
+ },
+ "assignee": null,
+ "source_project_id": 1,
+ "target_project_id": 1,
+ "labels": [],
+ "work_in_progress": false,
+ "milestone": null,
+ "merge_when_pipeline_succeeds": false,
+ "merge_status": "unchecked",
+ "sha": "5a62481d563af92b8e32d735f2fa63b94e806835",
+ "merge_commit_sha": null,
+ "user_notes_count": 1,
+ "should_remove_source_branch": null,
+ "force_remove_source_branch": false,
+ "web_url": "https://gitlab.example.com/gitlab-org/gitlab-test/merge_requests/6432"
+ }
+]
+```
+
+
## Comments on issues
Comments are done via the [notes](notes.md) resource.
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
new file mode 100644
index 00000000000..297115e94ac
--- /dev/null
+++ b/doc/api/jobs.md
@@ -0,0 +1,617 @@
+# Jobs API
+
+## List project jobs
+
+Get a list of jobs in a project.
+
+```
+GET /projects/:id/jobs
+```
+
+| Attribute | Type | Required | Description |
+|-----------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `scope` | string **or** array of strings | no | The scope of jobs to show, one or array of: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, `manual`; showing all jobs if none provided |
+
+```
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/1/jobs?scope[]=pending&scope[]=running'
+```
+
+Example of response
+
+```json
+[
+ {
+ "commit": {
+ "author_email": "admin@example.com",
+ "author_name": "Administrator",
+ "created_at": "2015-12-24T16:51:14.000+01:00",
+ "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "message": "Test the CI integration.",
+ "short_id": "0ff3ae19",
+ "title": "Test the CI integration."
+ },
+ "coverage": null,
+ "created_at": "2015-12-24T15:51:21.802Z",
+ "artifacts_file": {
+ "filename": "artifacts.zip",
+ "size": 1000
+ },
+ "finished_at": "2015-12-24T17:54:27.895Z",
+ "id": 7,
+ "name": "teaspoon",
+ "pipeline": {
+ "id": 6,
+ "ref": "master",
+ "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "status": "pending"
+ },
+ "ref": "master",
+ "runner": null,
+ "stage": "test",
+ "started_at": "2015-12-24T17:54:27.722Z",
+ "status": "failed",
+ "tag": false,
+ "user": {
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "bio": null,
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "id": 1,
+ "linkedin": "",
+ "name": "Administrator",
+ "skype": "",
+ "state": "active",
+ "twitter": "",
+ "username": "root",
+ "web_url": "http://gitlab.dev/root",
+ "website_url": ""
+ }
+ },
+ {
+ "commit": {
+ "author_email": "admin@example.com",
+ "author_name": "Administrator",
+ "created_at": "2015-12-24T16:51:14.000+01:00",
+ "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "message": "Test the CI integration.",
+ "short_id": "0ff3ae19",
+ "title": "Test the CI integration."
+ },
+ "coverage": null,
+ "created_at": "2015-12-24T15:51:21.727Z",
+ "artifacts_file": null,
+ "finished_at": "2015-12-24T17:54:24.921Z",
+ "id": 6,
+ "name": "spinach:other",
+ "pipeline": {
+ "id": 6,
+ "ref": "master",
+ "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "status": "pending"
+ },
+ "ref": "master",
+ "runner": null,
+ "stage": "test",
+ "started_at": "2015-12-24T17:54:24.729Z",
+ "status": "failed",
+ "tag": false,
+ "user": {
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "bio": null,
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "id": 1,
+ "linkedin": "",
+ "name": "Administrator",
+ "skype": "",
+ "state": "active",
+ "twitter": "",
+ "username": "root",
+ "web_url": "http://gitlab.dev/root",
+ "website_url": ""
+ }
+ }
+]
+```
+
+## List pipeline jobs
+
+Get a list of jobs for a pipeline.
+
+```
+GET /projects/:id/pipelines/:pipeline_id/jobs
+```
+
+| Attribute | Type | Required | Description |
+|---------------|--------------------------------|----------|----------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `pipeline_id` | integer | yes | The ID of a pipeline |
+| `scope` | string **or** array of strings | no | The scope of jobs to show, one or array of: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, `manual`; showing all jobs if none provided |
+
+```
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/1/pipelines/6/jobs?scope[]=pending&scope[]=running'
+```
+
+Example of response
+
+```json
+[
+ {
+ "commit": {
+ "author_email": "admin@example.com",
+ "author_name": "Administrator",
+ "created_at": "2015-12-24T16:51:14.000+01:00",
+ "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "message": "Test the CI integration.",
+ "short_id": "0ff3ae19",
+ "title": "Test the CI integration."
+ },
+ "coverage": null,
+ "created_at": "2015-12-24T15:51:21.802Z",
+ "artifacts_file": {
+ "filename": "artifacts.zip",
+ "size": 1000
+ },
+ "finished_at": "2015-12-24T17:54:27.895Z",
+ "id": 7,
+ "name": "teaspoon",
+ "pipeline": {
+ "id": 6,
+ "ref": "master",
+ "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "status": "pending"
+ },
+ "ref": "master",
+ "runner": null,
+ "stage": "test",
+ "started_at": "2015-12-24T17:54:27.722Z",
+ "status": "failed",
+ "tag": false,
+ "user": {
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "bio": null,
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "id": 1,
+ "linkedin": "",
+ "name": "Administrator",
+ "skype": "",
+ "state": "active",
+ "twitter": "",
+ "username": "root",
+ "web_url": "http://gitlab.dev/root",
+ "website_url": ""
+ }
+ },
+ {
+ "commit": {
+ "author_email": "admin@example.com",
+ "author_name": "Administrator",
+ "created_at": "2015-12-24T16:51:14.000+01:00",
+ "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "message": "Test the CI integration.",
+ "short_id": "0ff3ae19",
+ "title": "Test the CI integration."
+ },
+ "coverage": null,
+ "created_at": "2015-12-24T15:51:21.727Z",
+ "artifacts_file": null,
+ "finished_at": "2015-12-24T17:54:24.921Z",
+ "id": 6,
+ "name": "spinach:other",
+ "pipeline": {
+ "id": 6,
+ "ref": "master",
+ "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "status": "pending"
+ },
+ "ref": "master",
+ "runner": null,
+ "stage": "test",
+ "started_at": "2015-12-24T17:54:24.729Z",
+ "status": "failed",
+ "tag": false,
+ "user": {
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "bio": null,
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "id": 1,
+ "linkedin": "",
+ "name": "Administrator",
+ "skype": "",
+ "state": "active",
+ "twitter": "",
+ "username": "root",
+ "web_url": "http://gitlab.dev/root",
+ "website_url": ""
+ }
+ }
+]
+```
+
+## Get a single job
+
+Get a single job of a project
+
+```
+GET /projects/:id/jobs/:job_id
+```
+
+| Attribute | Type | Required | Description |
+|------------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `job_id` | integer | yes | The ID of a job |
+
+```
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/8"
+```
+
+Example of response
+
+```json
+{
+ "commit": {
+ "author_email": "admin@example.com",
+ "author_name": "Administrator",
+ "created_at": "2015-12-24T16:51:14.000+01:00",
+ "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "message": "Test the CI integration.",
+ "short_id": "0ff3ae19",
+ "title": "Test the CI integration."
+ },
+ "coverage": null,
+ "created_at": "2015-12-24T15:51:21.880Z",
+ "artifacts_file": null,
+ "finished_at": "2015-12-24T17:54:31.198Z",
+ "id": 8,
+ "name": "rubocop",
+ "pipeline": {
+ "id": 6,
+ "ref": "master",
+ "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "status": "pending"
+ },
+ "ref": "master",
+ "runner": null,
+ "stage": "test",
+ "started_at": "2015-12-24T17:54:30.733Z",
+ "status": "failed",
+ "tag": false,
+ "user": {
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "bio": null,
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "id": 1,
+ "linkedin": "",
+ "name": "Administrator",
+ "skype": "",
+ "state": "active",
+ "twitter": "",
+ "username": "root",
+ "web_url": "http://gitlab.dev/root",
+ "website_url": ""
+ }
+}
+```
+
+## Get job artifacts
+
+> [Introduced][ce-2893] in GitLab 8.5
+
+Get job artifacts of a project
+
+```
+GET /projects/:id/jobs/:job_id/artifacts
+```
+
+| Attribute | Type | Required | Description |
+|------------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `job_id` | integer | yes | The ID of a job |
+
+```
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/8/artifacts"
+```
+
+Response:
+
+| Status | Description |
+|-----------|---------------------------------|
+| 200 | Serves the artifacts file |
+| 404 | Build not found or no artifacts |
+
+[ce-2893]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2893
+
+## Download the artifacts file
+
+> [Introduced][ce-5347] in GitLab 8.10.
+
+Download the artifacts file from the given reference name and job provided the
+job finished successfully.
+
+```
+GET /projects/:id/jobs/artifacts/:ref_name/download?job=name
+```
+
+Parameters
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|-------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `ref_name` | string | yes | The ref from a repository |
+| `job` | string | yes | The name of the job |
+
+Example request:
+
+```
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/download?job=test"
+```
+
+Example response:
+
+| Status | Description |
+|-----------|---------------------------------|
+| 200 | Serves the artifacts file |
+| 404 | Build not found or no artifacts |
+
+[ce-5347]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5347
+
+## Get a trace file
+
+Get a trace of a specific job of a project
+
+```
+GET /projects/:id/jobs/:job_id/trace
+```
+
+| Attribute | Type | Required | Description |
+|------------|---------|----------|---------------------|
+| id | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| job_id | integer | yes | The ID of a job |
+
+```
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/8/trace"
+```
+
+Response:
+
+| Status | Description |
+|-----------|-----------------------------------|
+| 200 | Serves the trace file |
+| 404 | Build not found or no trace file |
+
+## Cancel a job
+
+Cancel a single job of a project
+
+```
+POST /projects/:id/jobs/:job_id/cancel
+```
+
+| Attribute | Type | Required | Description |
+|------------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `job_id` | integer | yes | The ID of a job |
+
+```
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/cancel"
+```
+
+Example of response
+
+```json
+{
+ "commit": {
+ "author_email": "admin@example.com",
+ "author_name": "Administrator",
+ "created_at": "2015-12-24T16:51:14.000+01:00",
+ "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "message": "Test the CI integration.",
+ "short_id": "0ff3ae19",
+ "title": "Test the CI integration."
+ },
+ "coverage": null,
+ "created_at": "2016-01-11T10:13:33.506Z",
+ "artifacts_file": null,
+ "finished_at": "2016-01-11T10:14:09.526Z",
+ "id": 69,
+ "name": "rubocop",
+ "ref": "master",
+ "runner": null,
+ "stage": "test",
+ "started_at": null,
+ "status": "canceled",
+ "tag": false,
+ "user": null
+}
+```
+
+## Retry a job
+
+Retry a single job of a project
+
+```
+POST /projects/:id/jobs/:job_id/retry
+```
+
+| Attribute | Type | Required | Description |
+|------------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `job_id` | integer | yes | The ID of a job |
+
+```
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/retry"
+```
+
+Example of response
+
+```json
+{
+ "commit": {
+ "author_email": "admin@example.com",
+ "author_name": "Administrator",
+ "created_at": "2015-12-24T16:51:14.000+01:00",
+ "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "message": "Test the CI integration.",
+ "short_id": "0ff3ae19",
+ "title": "Test the CI integration."
+ },
+ "coverage": null,
+ "created_at": "2016-01-11T10:13:33.506Z",
+ "artifacts_file": null,
+ "finished_at": null,
+ "id": 69,
+ "name": "rubocop",
+ "ref": "master",
+ "runner": null,
+ "stage": "test",
+ "started_at": null,
+ "status": "pending",
+ "tag": false,
+ "user": null
+}
+```
+
+## Erase a job
+
+Erase a single job of a project (remove job artifacts and a job trace)
+
+```
+POST /projects/:id/jobs/:job_id/erase
+```
+
+Parameters
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `job_id` | integer | yes | The ID of a job |
+
+Example of request
+
+```
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/erase"
+```
+
+Example of response
+
+```json
+{
+ "commit": {
+ "author_email": "admin@example.com",
+ "author_name": "Administrator",
+ "created_at": "2015-12-24T16:51:14.000+01:00",
+ "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "message": "Test the CI integration.",
+ "short_id": "0ff3ae19",
+ "title": "Test the CI integration."
+ },
+ "coverage": null,
+ "download_url": null,
+ "id": 69,
+ "name": "rubocop",
+ "ref": "master",
+ "runner": null,
+ "stage": "test",
+ "created_at": "2016-01-11T10:13:33.506Z",
+ "started_at": "2016-01-11T10:13:33.506Z",
+ "finished_at": "2016-01-11T10:15:10.506Z",
+ "status": "failed",
+ "tag": false,
+ "user": null
+}
+```
+
+## Keep artifacts
+
+Prevents artifacts from being deleted when expiration is set.
+
+```
+POST /projects/:id/jobs/:job_id/artifacts/keep
+```
+
+Parameters
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `job_id` | integer | yes | The ID of a job |
+
+Example request:
+
+```
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/artifacts/keep"
+```
+
+Example response:
+
+```json
+{
+ "commit": {
+ "author_email": "admin@example.com",
+ "author_name": "Administrator",
+ "created_at": "2015-12-24T16:51:14.000+01:00",
+ "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "message": "Test the CI integration.",
+ "short_id": "0ff3ae19",
+ "title": "Test the CI integration."
+ },
+ "coverage": null,
+ "download_url": null,
+ "id": 69,
+ "name": "rubocop",
+ "ref": "master",
+ "runner": null,
+ "stage": "test",
+ "created_at": "2016-01-11T10:13:33.506Z",
+ "started_at": "2016-01-11T10:13:33.506Z",
+ "finished_at": "2016-01-11T10:15:10.506Z",
+ "status": "failed",
+ "tag": false,
+ "user": null
+}
+```
+
+## Play a job
+
+Triggers a manual action to start a job.
+
+```
+POST /projects/:id/jobs/:job_id/play
+```
+
+| Attribute | Type | Required | Description |
+|-----------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `job_id` | integer | yes | The ID of a job |
+
+```
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/play"
+```
+
+Example of response
+
+```json
+{
+ "commit": {
+ "author_email": "admin@example.com",
+ "author_name": "Administrator",
+ "created_at": "2015-12-24T16:51:14.000+01:00",
+ "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
+ "message": "Test the CI integration.",
+ "short_id": "0ff3ae19",
+ "title": "Test the CI integration."
+ },
+ "coverage": null,
+ "created_at": "2016-01-11T10:13:33.506Z",
+ "artifacts_file": null,
+ "finished_at": null,
+ "id": 69,
+ "name": "rubocop",
+ "ref": "master",
+ "runner": null,
+ "stage": "test",
+ "started_at": null,
+ "status": "started",
+ "tag": false,
+ "user": null
+}
+```
diff --git a/doc/api/keys.md b/doc/api/keys.md
index faa6f212b43..376ac27df3a 100644
--- a/doc/api/keys.md
+++ b/doc/api/keys.md
@@ -1,4 +1,4 @@
-# Keys
+# Keys API
## Get SSH key with user by ID of an SSH key
@@ -24,16 +24,14 @@ Parameters:
"id": 25,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/cfa35b8cd2ec278026357769582fa563?s=40\u0026d=identicon",
- "web_url": "http://localhost:3000/u/john_smith",
+ "web_url": "http://localhost:3000/john_smith",
"created_at": "2015-09-03T07:24:01.670Z",
- "is_admin": false,
"bio": null,
"skype": "",
"linkedin": "",
"twitter": "",
"website_url": "",
"email": "john@example.com",
- "theme_id": 2,
"color_scheme_id": 1,
"projects_limit": 10,
"current_sign_in_at": null,
diff --git a/doc/api/labels.md b/doc/api/labels.md
index 3653ccf304a..ec93cf50e7a 100644
--- a/doc/api/labels.md
+++ b/doc/api/labels.md
@@ -1,4 +1,4 @@
-# Labels
+# Labels API
## List labels
@@ -10,56 +10,71 @@ GET /projects/:id/labels
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
-| `id` | integer | yes | The ID of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/1/labels
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/labels
```
Example response:
```json
[
- {
- "name" : "bug",
- "color" : "#d9534f",
- "description": "Bug reported by user",
- "open_issues_count": 1,
- "closed_issues_count": 0,
- "open_merge_requests_count": 1
- },
- {
- "color" : "#d9534f",
- "name" : "confirmed",
- "description": "Confirmed issue",
- "open_issues_count": 2,
- "closed_issues_count": 5,
- "open_merge_requests_count": 0
- },
- {
- "name" : "critical",
- "color" : "#d9534f",
- "description": "Critical issue. Need fix ASAP",
- "open_issues_count": 1,
- "closed_issues_count": 3,
- "open_merge_requests_count": 1
- },
- {
- "name" : "documentation",
- "color" : "#f0ad4e",
- "description": "Issue about documentation",
- "open_issues_count": 1,
- "closed_issues_count": 0,
- "open_merge_requests_count": 2
- },
- {
- "color" : "#5cb85c",
- "name" : "enhancement",
- "description": "Enhancement proposal",
- "open_issues_count": 1,
- "closed_issues_count": 0,
- "open_merge_requests_count": 1
- }
+ {
+ "id" : 1,
+ "name" : "bug",
+ "color" : "#d9534f",
+ "description": "Bug reported by user",
+ "open_issues_count": 1,
+ "closed_issues_count": 0,
+ "open_merge_requests_count": 1,
+ "subscribed": false,
+ "priority": 10
+ },
+ {
+ "id" : 4,
+ "color" : "#d9534f",
+ "name" : "confirmed",
+ "description": "Confirmed issue",
+ "open_issues_count": 2,
+ "closed_issues_count": 5,
+ "open_merge_requests_count": 0,
+ "subscribed": false,
+ "priority": null
+ },
+ {
+ "id" : 7,
+ "name" : "critical",
+ "color" : "#d9534f",
+ "description": "Critical issue. Need fix ASAP",
+ "open_issues_count": 1,
+ "closed_issues_count": 3,
+ "open_merge_requests_count": 1,
+ "subscribed": false,
+ "priority": null
+ },
+ {
+ "id" : 8,
+ "name" : "documentation",
+ "color" : "#f0ad4e",
+ "description": "Issue about documentation",
+ "open_issues_count": 1,
+ "closed_issues_count": 0,
+ "open_merge_requests_count": 2,
+ "subscribed": false,
+ "priority": null
+ },
+ {
+ "id" : 9,
+ "color" : "#5cb85c",
+ "name" : "enhancement",
+ "description": "Enhancement proposal",
+ "open_issues_count": 1,
+ "closed_issues_count": 0,
+ "open_merge_requests_count": 1,
+ "subscribed": true,
+ "priority": null
+ }
]
```
@@ -67,31 +82,35 @@ Example response:
Creates a new label for the given repository with the given name and color.
-It returns 200 if the label was successfully created, 400 for wrong parameters
-and 409 if the label already exists.
-
```
POST /projects/:id/labels
```
| Attribute | Type | Required | Description |
| ------------- | ------- | -------- | ---------------------------- |
-| `id` | integer | yes | The ID of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `name` | string | yes | The name of the label |
-| `color` | string | yes | The color of the label in 6-digit hex notation with leading `#` sign |
+| `color` | string | yes | The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the [CSS color names](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords) |
| `description` | string | no | The description of the label |
+| `priority` | integer | no | The priority of the label. Must be greater or equal than zero or `null` to remove the priority. |
```bash
-curl --data "name=feature&color=#5843AD" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/labels"
+curl --data "name=feature&color=#5843AD" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/labels"
```
Example response:
```json
{
- "name" : "feature",
- "color" : "#5843AD",
- "description":null
+ "id" : 10,
+ "name" : "feature",
+ "color" : "#5843AD",
+ "description":null,
+ "open_issues_count": 0,
+ "closed_issues_count": 0,
+ "open_merge_requests_count": 0,
+ "subscribed": false,
+ "priority": null
}
```
@@ -99,36 +118,17 @@ Example response:
Deletes a label with a given name.
-It returns 200 if the label was successfully deleted, 400 for wrong parameters
-and 404 if the label does not exist.
-In case of an error, an additional error message is returned.
-
```
DELETE /projects/:id/labels
```
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
-| `id` | integer | yes | The ID of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `name` | string | yes | The name of the label |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/labels?name=bug"
-```
-
-Example response:
-
-```json
-{
- "title" : "feature",
- "color" : "#5843AD",
- "description": "New feature proposal",
- "updated_at" : "2015-11-03T21:22:30.737Z",
- "template" : false,
- "project_id" : 1,
- "created_at" : "2015-11-03T21:22:30.737Z",
- "id" : 9
-}
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/labels?name=bug"
```
## Edit an existing label
@@ -136,102 +136,90 @@ Example response:
Updates an existing label with new name or new color. At least one parameter
is required, to update the label.
-It returns 200 if the label was successfully deleted, 400 for wrong parameters
-and 404 if the label does not exist.
-In case of an error, an additional error message is returned.
-
```
PUT /projects/:id/labels
```
| Attribute | Type | Required | Description |
| --------------- | ------- | --------------------------------- | ------------------------------- |
-| `id` | integer | yes | The ID of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `name` | string | yes | The name of the existing label |
-| `new_name` | string | yes if `color` if not provided | The new name of the label |
-| `color` | string | yes if `new_name` is not provided | The new color of the label in 6-digit hex notation with leading `#` sign |
+| `new_name` | string | yes if `color` is not provided | The new name of the label |
+| `color` | string | yes if `new_name` is not provided | The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the [CSS color names](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords) |
| `description` | string | no | The new description of the label |
+| `priority` | integer | no | The new priority of the label. Must be greater or equal than zero or `null` to remove the priority. |
+
```bash
-curl --request PUT --data "name=documentation&new_name=docs&color=#8E44AD&description=Documentation" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/labels"
+curl --request PUT --data "name=documentation&new_name=docs&color=#8E44AD&description=Documentation" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/labels"
```
Example response:
```json
{
- "color" : "#8E44AD",
- "name" : "docs",
- "description": "Documentation"
+ "id" : 8,
+ "name" : "docs",
+ "color" : "#8E44AD",
+ "description": "Documentation",
+ "open_issues_count": 1,
+ "closed_issues_count": 0,
+ "open_merge_requests_count": 2,
+ "subscribed": false,
+ "priority": null
}
```
## Subscribe to a label
-Subscribes the authenticated user to a label to receive notifications. If the
-operation is successful, status code `201` together with the updated label is
-returned. If the user is already subscribed to the label, the status code `304`
-is returned. If the project or label is not found, status code `404` is
-returned.
+Subscribes the authenticated user to a label to receive notifications.
+If the user is already subscribed to the label, the status code `304`
+is returned.
```
-POST /projects/:id/labels/:label_id/subscription
+POST /projects/:id/labels/:label_id/subscribe
```
| Attribute | Type | Required | Description |
| ---------- | ----------------- | -------- | ------------------------------------ |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer or string | yes | The ID or title of a project's label |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/labels/1/subscription
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/labels/1/subscribe
```
Example response:
```json
{
- "name": "Docs",
- "color": "#cc0033",
- "description": "",
- "open_issues_count": 0,
- "closed_issues_count": 0,
- "open_merge_requests_count": 0,
- "subscribed": true
+ "id" : 1,
+ "name" : "bug",
+ "color" : "#d9534f",
+ "description": "Bug reported by user",
+ "open_issues_count": 1,
+ "closed_issues_count": 0,
+ "open_merge_requests_count": 1,
+ "subscribed": true,
+ "priority": null
}
```
## Unsubscribe from a label
Unsubscribes the authenticated user from a label to not receive notifications
-from it. If the operation is successful, status code `200` together with the
-updated label is returned. If the user is not subscribed to the label, the
-status code `304` is returned. If the project or label is not found, status code
-`404` is returned.
+from it. If the user is not subscribed to the label, the
+status code `304` is returned.
```
-DELETE /projects/:id/labels/:label_id/subscription
+POST /projects/:id/labels/:label_id/unsubscribe
```
| Attribute | Type | Required | Description |
| ---------- | ----------------- | -------- | ------------------------------------ |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer or string | yes | The ID or title of a project's label |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/labels/1/subscription
-```
-
-Example response:
-
-```json
-{
- "name": "Docs",
- "color": "#cc0033",
- "description": "",
- "open_issues_count": 0,
- "closed_issues_count": 0,
- "open_merge_requests_count": 0,
- "subscribed": false
-}
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/labels/1/unsubscribe
```
diff --git a/doc/api/members.md b/doc/api/members.md
index 6535e9a7801..3234f833eae 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -1,4 +1,4 @@
-# Group and project members
+# Group and project members API
**Valid access levels**
@@ -16,8 +16,6 @@ The access levels are defined in the `Gitlab::Access` module. Currently, these l
Gets a list of group or project members viewable by the authenticated user.
-Returns `200` if the request succeeds.
-
```
GET /groups/:id/members
GET /projects/:id/members
@@ -25,12 +23,12 @@ GET /projects/:id/members
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The group/project ID or path |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `query` | string | no | A query string to search for members |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/:id/members
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/:id/members
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/members
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/members
```
Example response:
@@ -60,8 +58,6 @@ Example response:
Gets a member of a group or project.
-Returns `200` if the request succeeds.
-
```
GET /groups/:id/members/:user_id
GET /projects/:id/members/:user_id
@@ -69,12 +65,12 @@ GET /projects/:id/members/:user_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The group/project ID or path |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `user_id` | integer | yes | The user ID of the member |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/:id/members/:user_id
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/:id/members/:user_id
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/members/:user_id
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/members/:user_id
```
Example response:
@@ -95,8 +91,6 @@ Example response:
Adds a member to a group or project.
-Returns `201` if the request succeeds.
-
```
POST /groups/:id/members
POST /projects/:id/members
@@ -104,14 +98,14 @@ POST /projects/:id/members
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The group/project ID or path |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `user_id` | integer | yes | The user ID of the new member |
| `access_level` | integer | yes | A valid access level |
| `expires_at` | string | no | A date string in the format YEAR-MONTH-DAY |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "user_id=1&access_level=30" https://gitlab.example.com/api/v3/groups/:id/members
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "user_id=1&access_level=30" https://gitlab.example.com/api/v3/projects/:id/members
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "user_id=1&access_level=30" https://gitlab.example.com/api/v4/groups/:id/members
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "user_id=1&access_level=30" https://gitlab.example.com/api/v4/projects/:id/members
```
Example response:
@@ -131,8 +125,6 @@ Example response:
Updates a member of a group or project.
-Returns `200` if the request succeeds.
-
```
PUT /groups/:id/members/:user_id
PUT /projects/:id/members/:user_id
@@ -140,14 +132,14 @@ PUT /projects/:id/members/:user_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The group/project ID or path |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `user_id` | integer | yes | The user ID of the member |
| `access_level` | integer | yes | A valid access level |
| `expires_at` | string | no | A date string in the format YEAR-MONTH-DAY |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/:id/members/:user_id?access_level=40
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/:id/members/:user_id?access_level=40
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/members/:user_id?access_level=40
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/members/:user_id?access_level=40
```
Example response:
@@ -167,8 +159,6 @@ Example response:
Removes a user from a group or project.
-Returns `200` if the request succeeds.
-
```
DELETE /groups/:id/members/:user_id
DELETE /projects/:id/members/:user_id
@@ -176,10 +166,10 @@ DELETE /projects/:id/members/:user_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The group/project ID or path |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `user_id` | integer | yes | The user ID of the member |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/:id/members/:user_id
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/:id/members/:user_id
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/members/:user_id
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/members/:user_id
```
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 494040a1ce8..3dc808c196d 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -1,4 +1,4 @@
-# Merge requests
+# Merge requests API
## List merge requests
@@ -10,16 +10,24 @@ The pagination parameters `page` and `per_page` can be used to restrict the list
GET /projects/:id/merge_requests
GET /projects/:id/merge_requests?state=opened
GET /projects/:id/merge_requests?state=all
-GET /projects/:id/merge_requests?iid=42
+GET /projects/:id/merge_requests?iids[]=42&iids[]=43
+GET /projects/:id/merge_requests?milestone=release
+GET /projects/:id/merge_requests?labels=bug,reproduced
```
Parameters:
-- `id` (required) - The ID of a project
-- `iid` (optional) - Return the request having the given `iid`
-- `state` (optional) - Return `all` requests or just those that are `merged`, `opened` or `closed`
-- `order_by` (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
-- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer | yes | The ID of a project |
+| `iids` | Array[integer] | no | Return the request having the given `iid` |
+| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, or `merged`|
+| `order_by`| string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
+| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` |
+| `milestone` | string | no | Return merge requests for a specific milestone |
+| `labels` | string | no | Return merge requests matching a comma separated list of labels |
+| `created_after` | datetime | no | Return merge requests created after the given time (inclusive) |
+| `created_before` | datetime | no | Return merge requests created before the given time (inclusive) |
```json
[
@@ -65,9 +73,8 @@ Parameters:
"updated_at": "2015-02-02T19:49:26.013Z",
"due_date": null
},
- "merge_when_build_succeeds": true,
+ "merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : false,
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
@@ -83,13 +90,13 @@ Parameters:
Shows information about a single merge request.
```
-GET /projects/:id/merge_requests/:merge_request_id
+GET /projects/:id/merge_requests/:merge_request_iid
```
Parameters:
-- `id` (required) - The ID of a project
-- `merge_request_id` (required) - The ID of MR
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `merge_request_iid` (required) - The internal ID of the merge request
```json
{
@@ -134,7 +141,7 @@ Parameters:
"updated_at": "2015-02-02T19:49:26.013Z",
"due_date": null
},
- "merge_when_build_succeeds": true,
+ "merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
"subscribed" : true,
"sha": "8888888888888888888888888888888888888888",
@@ -151,13 +158,13 @@ Parameters:
Get a list of merge request commits.
```
-GET /projects/:id/merge_requests/:merge_request_id/commits
+GET /projects/:id/merge_requests/:merge_request_iid/commits
```
Parameters:
-- `id` (required) - The ID of a project
-- `merge_request_id` (required) - The ID of MR
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `merge_request_iid` (required) - The internal ID of the merge request
```json
@@ -188,13 +195,13 @@ Parameters:
Shows information about the merge request including its files and changes.
```
-GET /projects/:id/merge_requests/:merge_request_id/changes
+GET /projects/:id/merge_requests/:merge_request_iid/changes
```
Parameters:
-- `id` (required) - The ID of a project
-- `merge_request_id` (required) - The ID of MR
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `merge_request_iid` (required) - The internal ID of the merge request
```json
{
@@ -239,7 +246,7 @@ Parameters:
"updated_at": "2015-02-02T19:49:26.013Z",
"due_date": null
},
- "merge_when_build_succeeds": true,
+ "merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
"subscribed" : true,
"sha": "8888888888888888888888888888888888888888",
@@ -270,17 +277,18 @@ Creates a new merge request.
POST /projects/:id/merge_requests
```
-Parameters:
-
-- `id` (required) - The ID of a project
-- `source_branch` (required) - The source branch
-- `target_branch` (required) - The target branch
-- `assignee_id` (optional) - Assignee user ID
-- `title` (required) - Title of MR
-- `description` (optional) - Description of MR
-- `target_project_id` (optional) - The target project (numeric id)
-- `labels` (optional) - Labels for MR as a comma-separated list
-- `milestone_id` (optional) - Milestone ID
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `source_branch` | string | yes | The source branch |
+| `target_branch` | string | yes | The target branch |
+| `title` | string | yes | Title of MR |
+| `assignee_id` | integer | no | Assignee user ID |
+| `description` | string | no | Description of MR |
+| `target_project_id` | integer | no | The target project (numeric id) |
+| `labels` | string | no | Labels for MR as a comma-separated list |
+| `milestone_id` | integer | no | The ID of a milestone |
+| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging |
```json
{
@@ -325,7 +333,7 @@ Parameters:
"updated_at": "2015-02-02T19:49:26.013Z",
"due_date": null
},
- "merge_when_build_succeeds": true,
+ "merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
"subscribed" : true,
"sha": "8888888888888888888888888888888888888888",
@@ -337,28 +345,28 @@ Parameters:
}
```
-If the operation is successful, 200 and the newly created merge request is returned.
-If an error occurs, an error number and a message explaining the reason is returned.
-
## Update MR
Updates an existing merge request. You can change the target branch, title, or even close the MR.
```
-PUT /projects/:id/merge_requests/:merge_request_id
+PUT /projects/:id/merge_requests/:merge_request_iid
```
-Parameters:
-
-- `id` (required) - The ID of a project
-- `merge_request_id` (required) - ID of MR
-- `target_branch` - The target branch
-- `assignee_id` - Assignee user ID
-- `title` - Title of MR
-- `description` - Description of MR
-- `state_event` - New state (close|reopen|merge)
-- `labels` (optional) - Labels for MR as a comma-separated list
-- `milestone_id` (optional) - Milestone ID
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The ID of a merge request |
+| `target_branch` | string | no | The target branch |
+| `title` | string | no | Title of MR |
+| `assignee_id` | integer | no | Assignee user ID |
+| `description` | string | no | Description of MR |
+| `state_event` | string | no | New state (close/reopen) |
+| `labels` | string | no | Labels for MR as a comma-separated list |
+| `milestone_id` | integer | no | The ID of a milestone |
+| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging |
+
+Must include at least one non-required attribute from above.
```json
{
@@ -402,7 +410,7 @@ Parameters:
"updated_at": "2015-02-02T19:49:26.013Z",
"due_date": null
},
- "merge_when_build_succeeds": true,
+ "merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
"subscribed" : true,
"sha": "8888888888888888888888888888888888888888",
@@ -414,53 +422,47 @@ Parameters:
}
```
-If the operation is successful, 200 and the updated merge request is returned.
-If an error occurs, an error number and a message explaining the reason is returned.
-
## Delete a merge request
Only for admins and project owners. Soft deletes the merge request in question.
-If the operation is successful, a status code `200` is returned. In case you cannot
-destroy this merge request, or it is not present, code `404` is given.
```
-DELETE /projects/:id/merge_requests/:merge_request_id
+DELETE /projects/:id/merge_requests/:merge_request_iid
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `merge_request_id` | integer | yes | The ID of a project's merge request |
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/4/merge_request/85
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/merge_requests/85
```
## Accept MR
Merge changes submitted with MR using this API.
-If the merge succeeds you'll get a `200 OK`.
-If it has some conflicts and can not be merged - you'll get a 405 and the error message 'Branch cannot be merged'
+If it has some conflicts and can not be merged - you'll get a `405` and the error message 'Branch cannot be merged'
-If merge request is already merged or closed - you'll get a 406 and the error message 'Method Not Allowed'
+If merge request is already merged or closed - you'll get a `406` and the error message 'Method Not Allowed'
-If the `sha` parameter is passed and does not match the HEAD of the source - you'll get a 409 and the error message 'SHA does not match HEAD of source branch'
+If the `sha` parameter is passed and does not match the HEAD of the source - you'll get a `409` and the error message 'SHA does not match HEAD of source branch'
-If you don't have permissions to accept this merge request - you'll get a 401
+If you don't have permissions to accept this merge request - you'll get a `401`
```
-PUT /projects/:id/merge_requests/:merge_request_id/merge
+PUT /projects/:id/merge_requests/:merge_request_iid/merge
```
Parameters:
-- `id` (required) - The ID of a project
-- `merge_request_id` (required) - ID of MR
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `merge_request_iid` (required) - Internal ID of MR
- `merge_commit_message` (optional) - Custom merge commit message
- `should_remove_source_branch` (optional) - if `true` removes the source branch
-- `merge_when_build_succeeds` (optional) - if `true` the MR is merged when the build succeeds
+- `merge_when_pipeline_succeeds` (optional) - if `true` the MR is merged when the pipeline succeeds
- `sha` (optional) - if present, then this SHA must match the HEAD of the source branch, otherwise the merge will fail
```json
@@ -506,7 +508,7 @@ Parameters:
"updated_at": "2015-02-02T19:49:26.013Z",
"due_date": null
},
- "merge_when_build_succeeds": true,
+ "merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
"subscribed" : true,
"sha": "8888888888888888888888888888888888888888",
@@ -518,22 +520,20 @@ Parameters:
}
```
-## Cancel Merge When Build Succeeds
-
-If successful you'll get `200 OK`.
+## Cancel Merge When Pipeline Succeeds
-If you don't have permissions to accept this merge request - you'll get a 401
+If you don't have permissions to accept this merge request - you'll get a `401`
-If the merge request is already merged or closed - you get 405 and error message 'Method Not Allowed'
+If the merge request is already merged or closed - you get `405` and error message 'Method Not Allowed'
-In case the merge request is not set to be merged when the build succeeds, you'll also get a 406 error.
+In case the merge request is not set to be merged when the pipeline succeeds, you'll also get a `406` error.
```
-PUT /projects/:id/merge_requests/:merge_request_id/cancel_merge_when_build_succeeds
+PUT /projects/:id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_succeeds
```
Parameters:
-- `id` (required) - The ID of a project
-- `merge_request_id` (required) - ID of MR
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `merge_request_iid` (required) - Internal ID of MR
```json
{
@@ -578,7 +578,7 @@ Parameters:
"updated_at": "2015-02-02T19:49:26.013Z",
"due_date": null
},
- "merge_when_build_succeeds": true,
+ "merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
"subscribed" : true,
"sha": "8888888888888888888888888888888888888888",
@@ -599,16 +599,16 @@ Comments are done via the [notes](notes.md) resource.
Get all the issues that would be closed by merging the provided merge request.
```
-GET /projects/:id/merge_requests/:merge_request_id/closes_issues
+GET /projects/:id/merge_requests/:merge_request_iid/closes_issues
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `merge_request_id` | integer | yes | The ID of the merge request |
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/76/merge_requests/1/closes_issues
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/76/merge_requests/1/closes_issues
```
Example response when the GitLab issue tracker is used:
@@ -621,7 +621,7 @@ Example response when the GitLab issue tracker is used:
"author" : {
"state" : "active",
"id" : 18,
- "web_url" : "https://gitlab.example.com/u/eileen.lowe",
+ "web_url" : "https://gitlab.example.com/eileen.lowe",
"name" : "Alexandra Bashirian",
"avatar_url" : null,
"username" : "eileen.lowe"
@@ -642,7 +642,7 @@ Example response when the GitLab issue tracker is used:
"state" : "active",
"id" : 1,
"name" : "Administrator",
- "web_url" : "https://gitlab.example.com/u/root",
+ "web_url" : "https://gitlab.example.com/root",
"avatar_url" : null,
"username" : "root"
},
@@ -670,23 +670,20 @@ Example response when an external issue tracker (e.g. JIRA) is used:
## Subscribe to a merge request
-Subscribes the authenticated user to a merge request to receive notification. If
-the operation is successful, status code `201` together with the updated merge
-request is returned. If the user is already subscribed to the merge request, the
-status code `304` is returned. If the project or merge request is not found,
-status code `404` is returned.
+Subscribes the authenticated user to a merge request to receive notification. If the user is already subscribed to the merge request, the
+status code `304` is returned.
```
-POST /projects/:id/merge_requests/:merge_request_id/subscription
+POST /projects/:id/merge_requests/:merge_request_iid/subscribe
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `merge_request_id` | integer | yes | The ID of the merge request |
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/merge_requests/17/subscription
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/17/subscribe
```
Example response:
@@ -711,7 +708,7 @@ Example response:
"id": 19,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/39ce4a2822cc896933ffbd68c1470e55?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/leila"
+ "web_url": "https://gitlab.example.com/leila"
},
"assignee": {
"name": "Celine Wehner",
@@ -719,7 +716,7 @@ Example response:
"id": 16,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/f4cd5605b769dd2ce405a27c6e6f2684?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/carli"
+ "web_url": "https://gitlab.example.com/carli"
},
"source_project_id": 5,
"target_project_id": 5,
@@ -736,7 +733,7 @@ Example response:
"updated_at": "2016-04-05T21:41:40.905Z",
"due_date": null
},
- "merge_when_build_succeeds": false,
+ "merge_when_pipeline_succeeds": false,
"merge_status": "cannot_be_merged",
"subscribed": true,
"sha": "8888888888888888888888888888888888888888",
@@ -747,22 +744,20 @@ Example response:
## Unsubscribe from a merge request
Unsubscribes the authenticated user from a merge request to not receive
-notifications from that merge request. If the operation is successful, status
-code `200` together with the updated merge request is returned. If the user is
-not subscribed to the merge request, the status code `304` is returned. If the
-project or merge request is not found, status code `404` is returned.
+notifications from that merge request. If the user is
+not subscribed to the merge request, the status code `304` is returned.
```
-DELETE /projects/:id/merge_requests/:merge_request_id/subscription
+POST /projects/:id/merge_requests/:merge_request_iid/unsubscribe
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `merge_request_id` | integer | yes | The ID of the merge request |
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/merge_requests/17/subscription
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/17/unsubscribe
```
Example response:
@@ -787,7 +782,7 @@ Example response:
"id": 19,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/39ce4a2822cc896933ffbd68c1470e55?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/leila"
+ "web_url": "https://gitlab.example.com/leila"
},
"assignee": {
"name": "Celine Wehner",
@@ -795,7 +790,7 @@ Example response:
"id": 16,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/f4cd5605b769dd2ce405a27c6e6f2684?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/carli"
+ "web_url": "https://gitlab.example.com/carli"
},
"source_project_id": 5,
"target_project_id": 5,
@@ -812,7 +807,7 @@ Example response:
"updated_at": "2016-04-05T21:41:40.905Z",
"due_date": null
},
- "merge_when_build_succeeds": false,
+ "merge_when_pipeline_succeeds": false,
"merge_status": "cannot_be_merged",
"subscribed": false,
"sha": "8888888888888888888888888888888888888888",
@@ -822,22 +817,21 @@ Example response:
## Create a todo
-Manually creates a todo for the current user on a merge request. If the
-request is successful, status code `200` together with the created todo is
-returned. If there already exists a todo for the user on that merge request,
+Manually creates a todo for the current user on a merge request.
+If there already exists a todo for the user on that merge request,
status code `304` is returned.
```
-POST /projects/:id/merge_requests/:merge_request_id/todo
+POST /projects/:id/merge_requests/:merge_request_iid/todo
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `merge_request_id` | integer | yes | The ID of the merge request |
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/merge_requests/27/todo
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/27/todo
```
Example response:
@@ -858,7 +852,7 @@ Example response:
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/root"
+ "web_url": "https://gitlab.example.com/root"
},
"action_name": "marked",
"target_type": "MergeRequest",
@@ -881,7 +875,7 @@ Example response:
"id": 14,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/a7fa515d53450023c83d62986d0658a8?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/francisca"
+ "web_url": "https://gitlab.example.com/francisca"
},
"assignee": {
"name": "Dr. Gabrielle Strosin",
@@ -889,7 +883,7 @@ Example response:
"id": 4,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/733005fcd7e6df12d2d8580171ccb966?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/barrett.krajcik"
+ "web_url": "https://gitlab.example.com/barrett.krajcik"
},
"source_project_id": 3,
"target_project_id": 3,
@@ -906,7 +900,7 @@ Example response:
"updated_at": "2016-06-17T07:47:33.840Z",
"due_date": null
},
- "merge_when_build_succeeds": false,
+ "merge_when_pipeline_succeeds": false,
"merge_status": "unchecked",
"subscribed": true,
"sha": "8888888888888888888888888888888888888888",
@@ -928,16 +922,16 @@ Example response:
Get a list of merge request diff versions.
```
-GET /projects/:id/merge_requests/:merge_request_id/versions
+GET /projects/:id/merge_requests/:merge_request_iid/versions
```
-| Attribute | Type | Required | Description |
-| --------- | ------- | -------- | --------------------- |
-| `id` | String | yes | The ID of the project |
-| `merge_request_id` | integer | yes | The ID of the merge request |
+| Attribute | Type | Required | Description |
+| --------- | ------- | -------- | --------------------- |
+| `id` | String | yes | The ID of the project |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/1/merge_requests/1/versions
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/merge_requests/1/versions
```
Example response:
@@ -969,17 +963,17 @@ Example response:
Get a single merge request diff version.
```
-GET /projects/:id/merge_requests/:merge_request_id/versions/:version_id
+GET /projects/:id/merge_requests/:merge_request_iid/versions/:version_id
```
-| Attribute | Type | Required | Description |
-| --------- | ------- | -------- | --------------------- |
-| `id` | String | yes | The ID of the project |
-| `merge_request_id` | integer | yes | The ID of the merge request |
-| `version_id` | integer | yes | The ID of the merge request diff version |
+| Attribute | Type | Required | Description |
+| --------- | ------- | -------- | --------------------- |
+| `id` | String | yes | The ID of the project |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request |
+| `version_id` | integer | yes | The ID of the merge request diff version |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/1/merge_requests/1/versions/1
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/merge_requests/1/versions/1
```
Example response:
@@ -1031,3 +1025,142 @@ Example response:
}]
}
```
+## Set a time estimate for a merge request
+
+Sets an estimated time of work for this merge request.
+
+```
+POST /projects/:id/merge_requests/:merge_request_iid/time_estimate
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request |
+| `duration` | string | yes | The duration in human format. e.g: 3h30m |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_estimate?duration=3h30m
+```
+
+Example response:
+
+```json
+{
+ "human_time_estimate": "3h 30m",
+ "human_total_time_spent": null,
+ "time_estimate": 12600,
+ "total_time_spent": 0
+}
+```
+
+## Reset the time estimate for a merge request
+
+Resets the estimated time for this merge request to 0 seconds.
+
+```
+POST /projects/:id/merge_requests/:merge_request_iid/reset_time_estimate
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The internal ID of a project's merge_request |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_time_estimate
+```
+
+Example response:
+
+```json
+{
+ "human_time_estimate": null,
+ "human_total_time_spent": null,
+ "time_estimate": 0,
+ "total_time_spent": 0
+}
+```
+
+## Add spent time for a merge request
+
+Adds spent time for this merge request
+
+```
+POST /projects/:id/merge_requests/:merge_request_iid/add_spent_time
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request |
+| `duration` | string | yes | The duration in human format. e.g: 3h30m |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/add_spent_time?duration=1h
+```
+
+Example response:
+
+```json
+{
+ "human_time_estimate": null,
+ "human_total_time_spent": "1h",
+ "time_estimate": 0,
+ "total_time_spent": 3600
+}
+```
+
+## Reset spent time for a merge request
+
+Resets the total spent time for this merge request to 0 seconds.
+
+```
+POST /projects/:id/merge_requests/:merge_request_iid/reset_spent_time
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The internal ID of a project's merge_request |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_spent_time
+```
+
+Example response:
+
+```json
+{
+ "human_time_estimate": null,
+ "human_total_time_spent": null,
+ "time_estimate": 0,
+ "total_time_spent": 0
+}
+```
+
+## Get time tracking stats
+
+```
+GET /projects/:id/merge_requests/:merge_request_iid/time_stats
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request |
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_stats
+```
+
+Example response:
+
+```json
+{
+ "human_time_estimate": "2h",
+ "human_total_time_spent": "1h",
+ "time_estimate": 7200,
+ "total_time_spent": 3600
+}
+```
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
index ae7d22a4be5..a082d548499 100644
--- a/doc/api/milestones.md
+++ b/doc/api/milestones.md
@@ -1,4 +1,4 @@
-# Milestones
+# Milestones API
## List project milestones
@@ -6,21 +6,24 @@ Returns a list of project milestones.
```
GET /projects/:id/milestones
-GET /projects/:id/milestones?iid=42
+GET /projects/:id/milestones?iids=42
+GET /projects/:id/milestones?iids[]=42&iids[]=43
GET /projects/:id/milestones?state=active
GET /projects/:id/milestones?state=closed
+GET /projects/:id/milestones?search=version
```
Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `iid` | integer | optional | Return only the milestone having the given `iid` |
-| `state` | string | optional | Return only `active` or `closed` milestones` |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `iids` | Array[integer] | optional | Return only the milestones having the given `iids` |
+| `state` | string | optional | Return only `active` or `closed` milestones` |
+| `search` | string | optional | Return only milestones with a title or description matching the provided string |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/milestones
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/milestones
```
Example Response:
@@ -34,6 +37,7 @@ Example Response:
"title": "10.0",
"description": "Version",
"due_date": "2013-11-29",
+ "start_date": "2013-11-10",
"state": "active",
"updated_at": "2013-10-02T09:24:18Z",
"created_at": "2013-10-02T09:24:18Z"
@@ -52,8 +56,8 @@ GET /projects/:id/milestones/:milestone_id
Parameters:
-- `id` (required) - The ID of a project
-- `milestone_id` (required) - The ID of a project milestone
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `milestone_id` (required) - The ID of the project's milestone
## Create new milestone
@@ -65,10 +69,11 @@ POST /projects/:id/milestones
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `title` (required) - The title of an milestone
- `description` (optional) - The description of the milestone
- `due_date` (optional) - The due date of the milestone
+- `start_date` (optional) - The start date of the milestone
## Edit milestone
@@ -80,11 +85,12 @@ PUT /projects/:id/milestones/:milestone_id
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `milestone_id` (required) - The ID of a project milestone
- `title` (optional) - The title of a milestone
- `description` (optional) - The description of a milestone
- `due_date` (optional) - The due date of the milestone
+- `start_date` (optional) - The start date of the milestone
- `state_event` (optional) - The state event of the milestone (close|activate)
## Get all issues assigned to a single milestone
@@ -97,5 +103,18 @@ GET /projects/:id/milestones/:milestone_id/issues
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `milestone_id` (required) - The ID of a project milestone
+
+## Get all merge requests assigned to a single milestone
+
+Gets all merge requests assigned to a single project milestone.
+
+```
+GET /projects/:id/milestones/:milestone_id/merge_requests
+```
+
+Parameters:
+
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `milestone_id` (required) - The ID of a project milestone
diff --git a/doc/api/namespaces.md b/doc/api/namespaces.md
index 88cd407d792..4ad6071a0ed 100644
--- a/doc/api/namespaces.md
+++ b/doc/api/namespaces.md
@@ -1,4 +1,4 @@
-# Namespaces
+# Namespaces API
Usernames and groupnames fall under a special category called namespaces.
@@ -19,7 +19,7 @@ GET /namespaces
Example request:
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/namespaces
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/namespaces
```
Example response:
@@ -35,6 +35,12 @@ Example response:
"id": 2,
"path": "group1",
"kind": "group"
+ },
+ {
+ "id": 3,
+ "path": "bar",
+ "kind": "group",
+ "full_path": "foo/bar",
}
]
```
@@ -54,7 +60,7 @@ GET /namespaces?search=foobar
Example request:
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/namespaces?search=twitter
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/namespaces?search=twitter
```
Example response:
@@ -64,7 +70,8 @@ Example response:
{
"id": 4,
"path": "twitter",
- "kind": "group"
+ "kind": "group",
+ "full_path": "twitter",
}
]
```
diff --git a/doc/api/notes.md b/doc/api/notes.md
index 572844b8b3f..388e6989df2 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -1,4 +1,4 @@
-# Notes
+# Notes API
Notes are comments on snippets, issues or merge requests.
@@ -9,19 +9,19 @@ Notes are comments on snippets, issues or merge requests.
Gets a list of all notes for a single issue.
```
-GET /projects/:id/issues/:issue_id/notes
+GET /projects/:id/issues/:issue_iid/notes
```
Parameters:
-- `id` (required) - The ID of a project
-- `issue_id` (required) - The ID of an issue
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `issue_iid` (required) - The IID of an issue
```json
[
{
"id": 302,
- "body": "Status changed to closed",
+ "body": "closed",
"attachment": null,
"author": {
"id": 1,
@@ -34,8 +34,6 @@ Parameters:
"created_at": "2013-10-02T09:22:45Z",
"updated_at": "2013-10-02T10:22:45Z",
"system": true,
- "upvote": false,
- "downvote": false,
"noteable_id": 377,
"noteable_type": "Issue"
},
@@ -54,8 +52,6 @@ Parameters:
"created_at": "2013-10-02T09:56:03Z",
"updated_at": "2013-10-02T09:56:03Z",
"system": true,
- "upvote": false,
- "downvote": false,
"noteable_id": 121,
"noteable_type": "Issue"
}
@@ -67,13 +63,13 @@ Parameters:
Returns a single note for a specific project issue
```
-GET /projects/:id/issues/:issue_id/notes/:note_id
+GET /projects/:id/issues/:issue_iid/notes/:note_id
```
Parameters:
-- `id` (required) - The ID of a project
-- `issue_id` (required) - The ID of a project issue
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `issue_iid` (required) - The IID of a project issue
- `note_id` (required) - The ID of an issue note
### Create new issue note
@@ -82,13 +78,13 @@ Creates a new note to a single project issue. If you create a note where the bod
only contains an Award Emoji, you'll receive this object back.
```
-POST /projects/:id/issues/:issue_id/notes
+POST /projects/:id/issues/:issue_iid/notes
```
Parameters:
-- `id` (required) - The ID of a project
-- `issue_id` (required) - The ID of an issue
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `issue_id` (required) - The IID of an issue
- `body` (required) - The content of a note
- `created_at` (optional) - Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z
@@ -97,61 +93,34 @@ Parameters:
Modify existing note of an issue.
```
-PUT /projects/:id/issues/:issue_id/notes/:note_id
+PUT /projects/:id/issues/:issue_iid/notes/:note_id
```
Parameters:
-- `id` (required) - The ID of a project
-- `issue_id` (required) - The ID of an issue
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `issue_iid` (required) - The IID of an issue
- `note_id` (required) - The ID of a note
- `body` (required) - The content of a note
### Delete an issue note
-Deletes an existing note of an issue. On success, this API method returns 200
-and the deleted note. If the note does not exist, the API returns 404.
+Deletes an existing note of an issue.
```
-DELETE /projects/:id/issues/:issue_id/notes/:note_id
+DELETE /projects/:id/issues/:issue_iid/notes/:note_id
```
Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `issue_id` | integer | yes | The ID of an issue |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The IID of an issue |
| `note_id` | integer | yes | The ID of a note |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/issues/11/notes/636
-```
-
-Example Response:
-
-```json
-{
- "id": 636,
- "body": "This is a good idea.",
- "attachment": null,
- "author": {
- "id": 1,
- "username": "pipin",
- "email": "admin@example.com",
- "name": "Pip",
- "state": "active",
- "created_at": "2013-09-30T13:46:01Z",
- "avatar_url": "http://www.gravatar.com/avatar/5224fd70153710e92fb8bcf79ac29d67?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/pipin"
- },
- "created_at": "2016-04-05T22:10:44.164Z",
- "system": false,
- "noteable_id": 11,
- "noteable_type": "Issue",
- "upvote": false,
- "downvote": false
-}
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/issues/11/notes/636
```
## Snippets
@@ -166,7 +135,7 @@ GET /projects/:id/snippets/:snippet_id/notes
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `snippet_id` (required) - The ID of a project snippet
### Get single snippet note
@@ -179,7 +148,7 @@ GET /projects/:id/snippets/:snippet_id/notes/:note_id
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `snippet_id` (required) - The ID of a project snippet
- `note_id` (required) - The ID of an snippet note
@@ -213,7 +182,7 @@ POST /projects/:id/snippets/:snippet_id/notes
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `snippet_id` (required) - The ID of a snippet
- `body` (required) - The content of a note
@@ -227,15 +196,14 @@ PUT /projects/:id/snippets/:snippet_id/notes/:note_id
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `snippet_id` (required) - The ID of a snippet
- `note_id` (required) - The ID of a note
- `body` (required) - The content of a note
### Delete a snippet note
-Deletes an existing note of a snippet. On success, this API method returns 200
-and the deleted note. If the note does not exist, the API returns 404.
+Deletes an existing note of a snippet.
```
DELETE /projects/:id/snippets/:snippet_id/notes/:note_id
@@ -245,38 +213,12 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `snippet_id` | integer | yes | The ID of a snippet |
| `note_id` | integer | yes | The ID of a note |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/snippets/52/notes/1659
-```
-
-Example Response:
-
-```json
-{
- "id": 1659,
- "body": "This is a good idea.",
- "attachment": null,
- "author": {
- "id": 1,
- "username": "pipin",
- "email": "admin@example.com",
- "name": "Pip",
- "state": "active",
- "created_at": "2013-09-30T13:46:01Z",
- "avatar_url": "http://www.gravatar.com/avatar/5224fd70153710e92fb8bcf79ac29d67?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/pipin"
- },
- "created_at": "2016-04-06T16:51:53.239Z",
- "system": false,
- "noteable_id": 52,
- "noteable_type": "Snippet",
- "upvote": false,
- "downvote": false
-}
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/snippets/52/notes/1659
```
## Merge Requests
@@ -286,26 +228,26 @@ Example Response:
Gets a list of all notes for a single merge request.
```
-GET /projects/:id/merge_requests/:merge_request_id/notes
+GET /projects/:id/merge_requests/:merge_request_iid/notes
```
Parameters:
-- `id` (required) - The ID of a project
-- `merge_request_id` (required) - The ID of a project merge request
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `merge_request_iid` (required) - The IID of a project merge request
### Get single merge request note
Returns a single note for a given merge request.
```
-GET /projects/:id/merge_requests/:merge_request_id/notes/:note_id
+GET /projects/:id/merge_requests/:merge_request_iid/notes/:note_id
```
Parameters:
-- `id` (required) - The ID of a project
-- `merge_request_id` (required) - The ID of a project merge request
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `merge_request_iid` (required) - The IID of a project merge request
- `note_id` (required) - The ID of a merge request note
```json
@@ -324,8 +266,6 @@ Parameters:
"created_at": "2013-10-02T08:57:14Z",
"updated_at": "2013-10-02T08:57:14Z",
"system": false,
- "upvote": false,
- "downvote": false,
"noteable_id": 2,
"noteable_type": "MergeRequest"
}
@@ -338,13 +278,13 @@ If you create a note where the body only contains an Award Emoji, you'll receive
this object back.
```
-POST /projects/:id/merge_requests/:merge_request_id/notes
+POST /projects/:id/merge_requests/:merge_request_iid/notes
```
Parameters:
-- `id` (required) - The ID of a project
-- `merge_request_id` (required) - The ID of a merge request
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `merge_request_iid` (required) - The IID of a merge request
- `body` (required) - The content of a note
### Modify existing merge request note
@@ -352,59 +292,32 @@ Parameters:
Modify existing note of a merge request.
```
-PUT /projects/:id/merge_requests/:merge_request_id/notes/:note_id
+PUT /projects/:id/merge_requests/:merge_request_iid/notes/:note_id
```
Parameters:
-- `id` (required) - The ID of a project
-- `merge_request_id` (required) - The ID of a merge request
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `merge_request_iid` (required) - The IID of a merge request
- `note_id` (required) - The ID of a note
- `body` (required) - The content of a note
### Delete a merge request note
-Deletes an existing note of a merge request. On success, this API method returns
-200 and the deleted note. If the note does not exist, the API returns 404.
+Deletes an existing note of a merge request.
```
-DELETE /projects/:id/merge_requests/:merge_request_id/notes/:note_id
+DELETE /projects/:id/merge_requests/:merge_request_iid/notes/:note_id
```
Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `merge_request_id` | integer | yes | The ID of a merge request |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The IID of a merge request |
| `note_id` | integer | yes | The ID of a note |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/merge_requests/7/notes/1602
-```
-
-Example Response:
-
-```json
-{
- "id": 1602,
- "body": "This is a good idea.",
- "attachment": null,
- "author": {
- "id": 1,
- "username": "pipin",
- "email": "admin@example.com",
- "name": "Pip",
- "state": "active",
- "created_at": "2013-09-30T13:46:01Z",
- "avatar_url": "http://www.gravatar.com/avatar/5224fd70153710e92fb8bcf79ac29d67?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/pipin"
- },
- "created_at": "2016-04-05T22:11:59.923Z",
- "system": false,
- "noteable_id": 7,
- "noteable_type": "MergeRequest",
- "upvote": false,
- "downvote": false
-}
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/merge_requests/7/notes/1602
```
diff --git a/doc/api/notification_settings.md b/doc/api/notification_settings.md
index ff6c9e4931c..3a2c398e355 100644
--- a/doc/api/notification_settings.md
+++ b/doc/api/notification_settings.md
@@ -1,10 +1,10 @@
-# Notification settings
+# Notification settings API
>**Note:** This feature was [introduced][ce-5632] in GitLab 8.12.
**Valid notification levels**
-The notification levels are defined in the `NotificationSetting::level` model enumeration. Currently, these levels are recognized:
+The notification levels are defined in the `NotificationSetting.level` model enumeration. Currently, these levels are recognized:
```
disabled
@@ -28,6 +28,8 @@ reopen_merge_request
close_merge_request
reassign_merge_request
merge_merge_request
+failed_pipeline
+success_pipeline
```
## Global notification settings
@@ -39,7 +41,7 @@ GET /notification_settings
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/notification_settings
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/notification_settings
```
Example response:
@@ -60,7 +62,7 @@ PUT /notification_settings
```
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/notification_settings?level=watch
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/notification_settings?level=watch
```
| Attribute | Type | Required | Description |
@@ -77,6 +79,8 @@ curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab
| `close_merge_request` | boolean | no | Enable/disable this notification |
| `reassign_merge_request` | boolean | no | Enable/disable this notification |
| `merge_merge_request` | boolean | no | Enable/disable this notification |
+| `failed_pipeline` | boolean | no | Enable/disable this notification |
+| `success_pipeline` | boolean | no | Enable/disable this notification |
Example response:
@@ -97,8 +101,8 @@ GET /projects/:id/notification_settings
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/5/notification_settings
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/8/notification_settings
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/5/notification_settings
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/8/notification_settings
```
| Attribute | Type | Required | Description |
@@ -123,8 +127,8 @@ PUT /projects/:id/notification_settings
```
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/5/notification_settings?level=watch
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/8/notification_settings?level=custom&new_note=true
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/5/notification_settings?level=watch
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/8/notification_settings?level=custom&new_note=true
```
| Attribute | Type | Required | Description |
@@ -141,6 +145,8 @@ curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab
| `close_merge_request` | boolean | no | Enable/disable this notification |
| `reassign_merge_request` | boolean | no | Enable/disable this notification |
| `merge_merge_request` | boolean | no | Enable/disable this notification |
+| `failed_pipeline` | boolean | no | Enable/disable this notification |
+| `success_pipeline` | boolean | no | Enable/disable this notification |
Example responses:
@@ -161,7 +167,9 @@ Example responses:
"reopen_merge_request": false,
"close_merge_request": false,
"reassign_merge_request": false,
- "merge_merge_request": false
+ "merge_merge_request": false,
+ "failed_pipeline": false,
+ "success_pipeline": false
}
}
```
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
index 5ef5e3f5744..07cb64cb373 100644
--- a/doc/api/oauth2.md
+++ b/doc/api/oauth2.md
@@ -57,7 +57,7 @@ Once you have the authorization code you can request an `access_token` using the
```
parameters = 'client_id=APP_ID&client_secret=APP_SECRET&code=RETURNED_CODE&grant_type=authorization_code&redirect_uri=REDIRECT_URI'
-RestClient.post 'http://localhost:3000/oauth/token', parameters
+RestClient.post 'http://gitlab.example.com/oauth/token', parameters
# The response will be
{
@@ -77,13 +77,13 @@ You can now make requests to the API with the access token returned.
The access token allows you to make requests to the API on a behalf of a user.
```
-GET https://localhost:3000/api/v3/user?access_token=OAUTH-TOKEN
+GET https://gitlab.example.com/api/v4/user?access_token=OAUTH-TOKEN
```
Or you can put the token to the Authorization header:
```
-curl --header "Authorization: Bearer OAUTH-TOKEN" https://localhost:3000/api/v3/user
+curl --header "Authorization: Bearer OAUTH-TOKEN" https://gitlab.example.com/api/v4/user
```
## Resource Owner Password Credentials
@@ -134,4 +134,4 @@ access_token = client.password.get_token('user@example.com', 'secret')
puts access_token.token
```
-[personal access tokens]: ./README.md#personal-access-tokens \ No newline at end of file
+[personal access tokens]: ../user/profile/personal_access_tokens.md
diff --git a/doc/api/pipeline_schedules.md b/doc/api/pipeline_schedules.md
new file mode 100644
index 00000000000..433654c18cc
--- /dev/null
+++ b/doc/api/pipeline_schedules.md
@@ -0,0 +1,273 @@
+# Pipeline schedules
+
+You can read more about [pipeline schedules](../user/project/pipelines/schedules.md).
+
+## Get all pipeline schedules
+
+Get a list of the pipeline schedules of a project.
+
+```
+GET /projects/:id/pipeline_schedules
+```
+
+| Attribute | Type | required | Description |
+|-----------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `scope` | string | no | The scope of pipeline schedules, one of: `active`, `inactive` |
+
+```sh
+curl --header "PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules"
+```
+
+```json
+[
+ {
+ "id": 13,
+ "description": "Test schedule pipeline",
+ "ref": "master",
+ "cron": "* * * * *",
+ "cron_timezone": "Asia/Tokyo",
+ "next_run_at": "2017-05-19T13:41:00.000Z",
+ "active": true,
+ "created_at": "2017-05-19T13:31:08.849Z",
+ "updated_at": "2017-05-19T13:40:17.727Z",
+ "owner": {
+ "name": "Administrator",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/root"
+ }
+ }
+]
+```
+
+## Get a single pipeline schedule
+
+Get the pipeline schedule of a project.
+
+```
+GET /projects/:id/pipeline_schedules/:pipeline_schedule_id
+```
+
+| Attribute | Type | required | Description |
+|--------------|---------|----------|--------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `pipeline_schedule_id` | integer | yes | The pipeline schedule id |
+
+```sh
+curl --header "PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13"
+```
+
+```json
+{
+ "id": 13,
+ "description": "Test schedule pipeline",
+ "ref": "master",
+ "cron": "* * * * *",
+ "cron_timezone": "Asia/Tokyo",
+ "next_run_at": "2017-05-19T13:41:00.000Z",
+ "active": true,
+ "created_at": "2017-05-19T13:31:08.849Z",
+ "updated_at": "2017-05-19T13:40:17.727Z",
+ "last_pipeline": {
+ "id": 332,
+ "sha": "0e788619d0b5ec17388dffb973ecd505946156db",
+ "ref": "master",
+ "status": "pending"
+ },
+ "owner": {
+ "name": "Administrator",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/root"
+ }
+}
+```
+
+## Create a new pipeline schedule
+
+Create a new pipeline schedule of a project.
+
+```
+POST /projects/:id/pipeline_schedules
+```
+
+| Attribute | Type | required | Description |
+|---------------|---------|----------|--------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `description` | string | yes | The description of pipeline schedule |
+| `ref` | string | yes | The branch/tag name will be triggered |
+| `cron ` | string | yes | The cron (e.g. `0 1 * * *`) ([Cron syntax](https://en.wikipedia.org/wiki/Cron)) |
+| `cron_timezone ` | string | no | The timezone supproted by `ActiveSupport::TimeZone` (e.g. `Pacific Time (US & Canada)`) (default: `'UTC'`) |
+| `active ` | boolean | no | The activation of pipeline schedule. If false is set, the pipeline schedule will deactivated initially (default: `true`) |
+
+```sh
+curl --request POST --header "PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ" --form description="Build packages" --form ref="master" --form cron="0 1 * * 5" --form cron_timezone="UTC" --form active="true" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules"
+```
+
+```json
+{
+ "id": 14,
+ "description": "Build packages",
+ "ref": "master",
+ "cron": "0 1 * * 5",
+ "cron_timezone": "UTC",
+ "next_run_at": "2017-05-26T01:00:00.000Z",
+ "active": true,
+ "created_at": "2017-05-19T13:43:08.169Z",
+ "updated_at": "2017-05-19T13:43:08.169Z",
+ "last_pipeline": null,
+ "owner": {
+ "name": "Administrator",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/root"
+ }
+}
+```
+
+## Edit a pipeline schedule
+
+Updates the pipeline schedule of a project. Once the update is done, it will be rescheduled automatically.
+
+```
+PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id
+```
+
+| Attribute | Type | required | Description |
+|---------------|---------|----------|--------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `pipeline_schedule_id` | integer | yes | The pipeline schedule id |
+| `description` | string | no | The description of pipeline schedule |
+| `ref` | string | no | The branch/tag name will be triggered |
+| `cron ` | string | no | The cron (e.g. `0 1 * * *`) ([Cron syntax](https://en.wikipedia.org/wiki/Cron)) |
+| `cron_timezone ` | string | no | The timezone supproted by `ActiveSupport::TimeZone` (e.g. `Pacific Time (US & Canada)`) or `TZInfo::Timezone` (e.g. `America/Los_Angeles`) |
+| `active ` | boolean | no | The activation of pipeline schedule. If false is set, the pipeline schedule will deactivated initially. |
+
+```sh
+curl --request PUT --header "PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ" --form cron="0 2 * * *" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13"
+```
+
+```json
+{
+ "id": 13,
+ "description": "Test schedule pipeline",
+ "ref": "master",
+ "cron": "0 2 * * *",
+ "cron_timezone": "Asia/Tokyo",
+ "next_run_at": "2017-05-19T17:00:00.000Z",
+ "active": true,
+ "created_at": "2017-05-19T13:31:08.849Z",
+ "updated_at": "2017-05-19T13:44:16.135Z",
+ "last_pipeline": {
+ "id": 332,
+ "sha": "0e788619d0b5ec17388dffb973ecd505946156db",
+ "ref": "master",
+ "status": "pending"
+ },
+ "owner": {
+ "name": "Administrator",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/root"
+ }
+}
+```
+
+## Take ownership of a pipeline schedule
+
+Update the owner of the pipeline schedule of a project.
+
+```
+POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/take_ownership
+```
+
+| Attribute | Type | required | Description |
+|---------------|---------|----------|--------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `pipeline_schedule_id` | integer | yes | The pipeline schedule id |
+
+```sh
+curl --request POST --header "PRIVATE-TOKEN: hf2CvZXB9w8Uc5pZKpSB" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/take_ownership"
+```
+
+```json
+{
+ "id": 13,
+ "description": "Test schedule pipeline",
+ "ref": "master",
+ "cron": "0 2 * * *",
+ "cron_timezone": "Asia/Tokyo",
+ "next_run_at": "2017-05-19T17:00:00.000Z",
+ "active": true,
+ "created_at": "2017-05-19T13:31:08.849Z",
+ "updated_at": "2017-05-19T13:46:37.468Z",
+ "last_pipeline": {
+ "id": 332,
+ "sha": "0e788619d0b5ec17388dffb973ecd505946156db",
+ "ref": "master",
+ "status": "pending"
+ },
+ "owner": {
+ "name": "shinya",
+ "username": "maeda",
+ "id": 50,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/8ca0a796a679c292e3a11da50f99e801?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/maeda"
+ }
+}
+```
+
+## Delete a pipeline schedule
+
+Delete the pipeline schedule of a project.
+
+```
+DELETE /projects/:id/pipeline_schedules/:pipeline_schedule_id
+```
+
+| Attribute | Type | required | Description |
+|----------------|---------|----------|--------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `pipeline_schedule_id` | integer | yes | The pipeline schedule id |
+
+```sh
+curl --request DELETE --header "PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13"
+```
+
+```json
+{
+ "id": 13,
+ "description": "Test schedule pipeline",
+ "ref": "master",
+ "cron": "0 2 * * *",
+ "cron_timezone": "Asia/Tokyo",
+ "next_run_at": "2017-05-19T17:00:00.000Z",
+ "active": true,
+ "created_at": "2017-05-19T13:31:08.849Z",
+ "updated_at": "2017-05-19T13:46:37.468Z",
+ "last_pipeline": {
+ "id": 332,
+ "sha": "0e788619d0b5ec17388dffb973ecd505946156db",
+ "ref": "master",
+ "status": "pending"
+ },
+ "owner": {
+ "name": "shinya",
+ "username": "maeda",
+ "id": 50,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/8ca0a796a679c292e3a11da50f99e801?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/maeda"
+ }
+}
+```
diff --git a/doc/api/pipeline_triggers.md b/doc/api/pipeline_triggers.md
new file mode 100644
index 00000000000..9030ae32d17
--- /dev/null
+++ b/doc/api/pipeline_triggers.md
@@ -0,0 +1,172 @@
+# Pipeline triggers API
+
+You can read more about [triggering pipelines through the API](../ci/triggers/README.md).
+
+## List project triggers
+
+Get a list of project's build triggers.
+
+```
+GET /projects/:id/triggers
+```
+
+| Attribute | Type | required | Description |
+|-----------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+
+```
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/triggers"
+```
+
+```json
+[
+ {
+ "id": 10,
+ "description": "my trigger",
+ "created_at": "2016-01-07T09:53:58.235Z",
+ "deleted_at": null,
+ "last_used": null,
+ "token": "6d056f63e50fe6f8c5f8f4aa10edb7",
+ "updated_at": "2016-01-07T09:53:58.235Z",
+ "owner": null
+ }
+]
+```
+
+## Get trigger details
+
+Get details of project's build trigger.
+
+```
+GET /projects/:id/triggers/:trigger_id
+```
+
+| Attribute | Type | required | Description |
+|--------------|---------|----------|--------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `trigger_id` | integer | yes | The trigger id |
+
+```
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/triggers/5"
+```
+
+```json
+{
+ "id": 10,
+ "description": "my trigger",
+ "created_at": "2016-01-07T09:53:58.235Z",
+ "deleted_at": null,
+ "last_used": null,
+ "token": "6d056f63e50fe6f8c5f8f4aa10edb7",
+ "updated_at": "2016-01-07T09:53:58.235Z",
+ "owner": null
+}
+```
+
+## Create a project trigger
+
+Create a trigger for a project.
+
+```
+POST /projects/:id/triggers
+```
+
+| Attribute | Type | required | Description |
+|---------------|---------|----------|--------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `description` | string | yes | The trigger name |
+
+```
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form description="my description" "https://gitlab.example.com/api/v4/projects/1/triggers"
+```
+
+```json
+{
+ "id": 10,
+ "description": "my trigger",
+ "created_at": "2016-01-07T09:53:58.235Z",
+ "deleted_at": null,
+ "last_used": null,
+ "token": "6d056f63e50fe6f8c5f8f4aa10edb7",
+ "updated_at": "2016-01-07T09:53:58.235Z",
+ "owner": null
+}
+```
+
+## Update a project trigger
+
+Update a trigger for a project.
+
+```
+PUT /projects/:id/triggers/:trigger_id
+```
+
+| Attribute | Type | required | Description |
+|---------------|---------|----------|--------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `trigger_id` | integer | yes | The trigger id |
+| `description` | string | no | The trigger name |
+
+```
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form description="my description" "https://gitlab.example.com/api/v4/projects/1/triggers/10"
+```
+
+```json
+{
+ "id": 10,
+ "description": "my trigger",
+ "created_at": "2016-01-07T09:53:58.235Z",
+ "deleted_at": null,
+ "last_used": null,
+ "token": "6d056f63e50fe6f8c5f8f4aa10edb7",
+ "updated_at": "2016-01-07T09:53:58.235Z",
+ "owner": null
+}
+```
+
+## Take ownership of a project trigger
+
+Update an owner of a project trigger.
+
+```
+POST /projects/:id/triggers/:trigger_id/take_ownership
+```
+
+| Attribute | Type | required | Description |
+|---------------|---------|----------|--------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `trigger_id` | integer | yes | The trigger id |
+
+```
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/triggers/10/take_ownership"
+```
+
+```json
+{
+ "id": 10,
+ "description": "my trigger",
+ "created_at": "2016-01-07T09:53:58.235Z",
+ "deleted_at": null,
+ "last_used": null,
+ "token": "6d056f63e50fe6f8c5f8f4aa10edb7",
+ "updated_at": "2016-01-07T09:53:58.235Z",
+ "owner": null
+}
+```
+
+## Remove a project trigger
+
+Remove a project's build trigger.
+
+```
+DELETE /projects/:id/triggers/:trigger_id
+```
+
+| Attribute | Type | required | Description |
+|----------------|---------|----------|--------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `trigger_id` | integer | yes | The trigger id |
+
+```
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/triggers/5"
+```
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index 847408a7f61..890945cfc7e 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -10,10 +10,18 @@ GET /projects/:id/pipelines
| Attribute | Type | Required | Description |
|-----------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `scope` | string | no | The scope of pipelines, one of: `running`, `pending`, `finished`, `branches`, `tags` |
+| `status` | string | no | The status of pipelines, one of: `running`, `pending`, `success`, `failed`, `canceled`, `skipped` |
+| `ref` | string | no | The ref of pipelines |
+| `yaml_errors`| boolean | no | Returns pipelines with invalid configurations |
+| `name`| string | no | The name of the user who triggered pipelines |
+| `username`| string | no | The username of the user who triggered pipelines |
+| `order_by`| string | no | Order pipelines by `id`, `status`, `ref`, or `user_id` (default: `id`) |
+| `sort` | string | no | Sort pipelines in `asc` or `desc` order (default: `desc`) |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/pipelines"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/pipelines"
```
Example of response
@@ -24,47 +32,13 @@ Example of response
"id": 47,
"status": "pending",
"ref": "new-pipeline",
- "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
- "before_sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
- "tag": false,
- "yaml_errors": null,
- "user": {
- "name": "Administrator",
- "username": "root",
- "id": 1,
- "state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://localhost:3000/u/root"
- },
- "created_at": "2016-08-16T10:23:19.007Z",
- "updated_at": "2016-08-16T10:23:19.216Z",
- "started_at": null,
- "finished_at": null,
- "committed_at": null,
- "duration": null
+ "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a"
},
{
"id": 48,
"status": "pending",
"ref": "new-pipeline",
- "sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a",
- "before_sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a",
- "tag": false,
- "yaml_errors": null,
- "user": {
- "name": "Administrator",
- "username": "root",
- "id": 1,
- "state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://localhost:3000/u/root"
- },
- "created_at": "2016-08-16T10:23:21.184Z",
- "updated_at": "2016-08-16T10:23:21.314Z",
- "started_at": null,
- "finished_at": null,
- "committed_at": null,
- "duration": null
+ "sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a"
}
]
```
@@ -79,11 +53,11 @@ GET /projects/:id/pipelines/:pipeline_id
| Attribute | Type | Required | Description |
|------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `pipeline_id` | integer | yes | The ID of a pipeline |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/pipeline/46"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/pipeline/46"
```
Example of response
@@ -103,18 +77,65 @@ Example of response
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://localhost:3000/u/root"
+ "web_url": "http://localhost:3000/root"
},
"created_at": "2016-08-11T11:28:34.085Z",
"updated_at": "2016-08-11T11:32:35.169Z",
"started_at": null,
"finished_at": "2016-08-11T11:32:35.145Z",
"committed_at": null,
- "duration": null
+ "duration": null,
+ "coverage": "30.0"
}
```
-## Retry failed builds in a pipeline
+## Create a new pipeline
+
+> [Introduced][ce-7209] in GitLab 8.14
+
+```
+POST /projects/:id/pipeline
+```
+
+| Attribute | Type | Required | Description |
+|------------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `ref` | string | yes | Reference to commit |
+
+```
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/pipeline?ref=master"
+```
+
+Example of response
+
+```json
+{
+ "id": 61,
+ "sha": "384c444e840a515b23f21915ee5766b87068a70d",
+ "ref": "master",
+ "status": "pending",
+ "before_sha": "0000000000000000000000000000000000000000",
+ "tag": false,
+ "yaml_errors": null,
+ "user": {
+ "name": "Administrator",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "http://localhost:3000/root"
+ },
+ "created_at": "2016-11-04T09:36:13.747Z",
+ "updated_at": "2016-11-04T09:36:13.977Z",
+ "started_at": null,
+ "finished_at": null,
+ "committed_at": null,
+ "duration": null,
+ "coverage": null
+}
+```
+
+## Retry jobs in a pipeline
> [Introduced][ce-5837] in GitLab 8.11
@@ -124,11 +145,11 @@ POST /projects/:id/pipelines/:pipeline_id/retry
| Attribute | Type | Required | Description |
|------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `pipeline_id` | integer | yes | The ID of a pipeline |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/pipelines/46/retry"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/pipelines/46/retry"
```
Response:
@@ -148,18 +169,19 @@ Response:
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://localhost:3000/u/root"
+ "web_url": "http://localhost:3000/root"
},
"created_at": "2016-08-11T11:28:34.085Z",
"updated_at": "2016-08-11T11:32:35.169Z",
"started_at": null,
"finished_at": "2016-08-11T11:32:35.145Z",
"committed_at": null,
- "duration": null
+ "duration": null,
+ "coverage": null
}
```
-## Cancel a pipelines builds
+## Cancel a pipelines jobs
> [Introduced][ce-5837] in GitLab 8.11
@@ -169,11 +191,11 @@ POST /projects/:id/pipelines/:pipeline_id/cancel
| Attribute | Type | Required | Description |
|------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `pipeline_id` | integer | yes | The ID of a pipeline |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/pipelines/46/cancel"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/pipelines/46/cancel"
```
Response:
@@ -193,15 +215,17 @@ Response:
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://localhost:3000/u/root"
+ "web_url": "http://localhost:3000/root"
},
"created_at": "2016-08-11T11:28:34.085Z",
"updated_at": "2016-08-11T11:32:35.169Z",
"started_at": null,
"finished_at": "2016-08-11T11:32:35.145Z",
"committed_at": null,
- "duration": null
+ "duration": null,
+ "coverage": null
}
```
[ce-5837]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5837
+[ce-7209]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7209
diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md
index c6685f54a9d..92491de4daa 100644
--- a/doc/api/project_snippets.md
+++ b/doc/api/project_snippets.md
@@ -3,15 +3,15 @@
### Snippet visibility level
Snippets in GitLab can be either private, internal or public.
-You can set it with the `visibility_level` field in the snippet.
+You can set it with the `visibility` field in the snippet.
Constants for snippet visibility levels are:
-| Visibility | visibility_level | Description |
-| ---------- | ---------------- | ----------- |
-| Private | `0` | The snippet is visible only the snippet creator |
-| Internal | `10` | The snippet is visible for any logged in user |
-| Public | `20` | The snippet can be accessed without any authentication |
+| visibility | Description |
+| ---------- | ----------- |
+| `private` | The snippet is visible only the snippet creator |
+| `internal` | The snippet is visible for any logged in user |
+| `public` | The snippet can be accessed without any authentication |
## List snippets
@@ -23,7 +23,7 @@ GET /projects/:id/snippets
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
## Single snippet
@@ -35,7 +35,7 @@ GET /projects/:id/snippets/:snippet_id
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `snippet_id` (required) - The ID of a project's snippet
```json
@@ -43,6 +43,7 @@ Parameters:
"id": 1,
"title": "test",
"file_name": "add.rb",
+ "description": "Ruby test snippet",
"author": {
"id": 1,
"username": "john_smith",
@@ -51,7 +52,6 @@ Parameters:
"state": "active",
"created_at": "2012-05-23T08:00:58Z"
},
- "expires_at": null,
"updated_at": "2012-06-28T10:52:04Z",
"created_at": "2012-06-28T10:52:04Z",
"web_url": "http://example.com/example/example/snippets/1"
@@ -68,11 +68,12 @@ POST /projects/:id/snippets
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `title` (required) - The title of a snippet
- `file_name` (required) - The name of a snippet file
+- `description` (optional) - The description of a snippet
- `code` (required) - The content of a snippet
-- `visibility_level` (required) - The snippet's visibility
+- `visibility` (required) - The snippet's visibility
## Update snippet
@@ -84,12 +85,13 @@ PUT /projects/:id/snippets/:snippet_id
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `snippet_id` (required) - The ID of a project's snippet
- `title` (optional) - The title of a snippet
- `file_name` (optional) - The name of a snippet file
+- `description` (optional) - The description of a snippet
- `code` (optional) - The content of a snippet
-- `visibility_level` (optional) - The snippet's visibility
+- `visibility` (optional) - The snippet's visibility
## Delete snippet
@@ -102,7 +104,7 @@ DELETE /projects/:id/snippets/:snippet_id
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `snippet_id` (required) - The ID of a project's snippet
## Snippet content
@@ -115,5 +117,5 @@ GET /projects/:id/snippets/:snippet_id/raw
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `snippet_id` (required) - The ID of a project's snippet
diff --git a/doc/api/projects.md b/doc/api/projects.md
index af229326eee..ea349ae8f68 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -1,26 +1,24 @@
-# Projects
-
+# Projects API
### Project visibility level
-Project in GitLab has be either private, internal or public.
-You can determine it by `visibility_level` field in project.
+Project in GitLab can be either private, internal or public.
+This is determined by the `visibility` field in the project.
-Constants for project visibility levels are next:
+Values for the project visibility level are:
-* Private. `visibility_level` is `0`.
+* `private`:
Project access must be granted explicitly for each user.
-* Internal. `visibility_level` is `10`.
+* `internal`:
The project can be cloned by any logged in user.
-* Public. `visibility_level` is `20`.
+* `public`:
The project can be cloned without any authentication.
-
## List projects
-Get a list of projects for which the authenticated user is a member.
+Get a list of visible projects for authenticated user. When accessed without authentication, only public projects are returned.
```
GET /projects
@@ -34,8 +32,14 @@ Parameters:
| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at` |
| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
-| `search` | string | no | Return list of authorized projects matching the search criteria |
+| `search` | string | no | Return list of projects matching the search criteria |
| `simple` | boolean | no | Return only the ID, URL, name, and path of each project |
+| `owned` | boolean | no | Limit by projects owned by the current user |
+| `membership` | boolean | no | Limit by projects that the current user is a member of |
+| `starred` | boolean | no | Limit by projects starred by the current user |
+| `statistics` | boolean | no | Include project statistics |
+| `with_issues_enabled` | boolean | no | Limit by enabled issues feature |
+| `with_merge_requests_enabled` | boolean | no | Limit by enabled merge requests feature |
```json
[
@@ -43,8 +47,7 @@ Parameters:
"id": 4,
"description": null,
"default_branch": "master",
- "public": false,
- "visibility_level": 0,
+ "visibility": "private",
"ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git",
"http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",
"web_url": "http://example.com/diaspora/diaspora-client",
@@ -64,7 +67,7 @@ Parameters:
"issues_enabled": true,
"open_issues_count": 1,
"merge_requests_enabled": true,
- "builds_enabled": true,
+ "jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"container_registry_enabled": false,
@@ -72,31 +75,37 @@ Parameters:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
- "created_at": "2013-09-30T13:46:02Z",
- "description": "",
"id": 3,
"name": "Diaspora",
- "owner_id": 1,
"path": "diaspora",
- "updated_at": "2013-09-30T13:46:02Z"
+ "kind": "group",
+ "full_path": "diaspora"
},
+ "import_status": "none",
"archived": false,
"avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png",
"shared_runners_enabled": true,
"forks_count": 0,
"star_count": 0,
"runners_token": "b8547b1dc37721d05889db52fa2f02",
- "public_builds": true,
+ "public_jobs": true,
"shared_with_groups": [],
- "only_allow_merge_if_build_succeeds": false,
- "request_access_enabled": false
+ "only_allow_merge_if_pipeline_succeeds": false,
+ "only_allow_merge_if_all_discussions_are_resolved": false,
+ "request_access_enabled": false,
+ "statistics": {
+ "commit_count": 37,
+ "storage_size": 1038090,
+ "repository_size": 1038090,
+ "lfs_objects_size": 0,
+ "job_artifacts_size": 0
+ }
},
{
"id": 6,
"description": null,
"default_branch": "master",
- "public": false,
- "visibility_level": 0,
+ "visibility": "private",
"ssh_url_to_repo": "git@example.com:brightbox/puppet.git",
"http_url_to_repo": "http://example.com/brightbox/puppet.git",
"web_url": "http://example.com/brightbox/puppet",
@@ -116,7 +125,7 @@ Parameters:
"issues_enabled": true,
"open_issues_count": 1,
"merge_requests_enabled": true,
- "builds_enabled": true,
+ "jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"container_registry_enabled": false,
@@ -124,14 +133,14 @@ Parameters:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
- "created_at": "2013-09-30T13:46:02Z",
- "description": "",
"id": 4,
"name": "Brightbox",
- "owner_id": 1,
"path": "brightbox",
- "updated_at": "2013-09-30T13:46:02Z"
+ "kind": "group",
+ "full_path": "brightbox"
},
+ "import_status": "none",
+ "import_error": null,
"permissions": {
"project_access": {
"access_level": 10,
@@ -148,204 +157,26 @@ Parameters:
"forks_count": 0,
"star_count": 0,
"runners_token": "b8547b1dc37721d05889db52fa2f02",
- "public_builds": true,
+ "public_jobs": true,
"shared_with_groups": [],
- "only_allow_merge_if_build_succeeds": false,
- "request_access_enabled": false
- }
-]
-```
-
-Get a list of projects which the authenticated user can see.
-
-```
-GET /projects/visible
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `archived` | boolean | no | Limit by archived status |
-| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
-| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at` |
-| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
-| `search` | string | no | Return list of authorized projects matching the search criteria |
-| `simple` | boolean | no | Return only the ID, URL, name, and path of each project |
-
-```json
-[
- {
- "id": 4,
- "description": null,
- "default_branch": "master",
- "public": false,
- "visibility_level": 0,
- "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git",
- "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",
- "web_url": "http://example.com/diaspora/diaspora-client",
- "tag_list": [
- "example",
- "disapora client"
- ],
- "owner": {
- "id": 3,
- "name": "Diaspora",
- "created_at": "2013-09-30T13:46:02Z"
- },
- "name": "Diaspora Client",
- "name_with_namespace": "Diaspora / Diaspora Client",
- "path": "diaspora-client",
- "path_with_namespace": "diaspora/diaspora-client",
- "issues_enabled": true,
- "open_issues_count": 1,
- "merge_requests_enabled": true,
- "builds_enabled": true,
- "wiki_enabled": true,
- "snippets_enabled": false,
- "container_registry_enabled": false,
- "created_at": "2013-09-30T13:46:02Z",
- "last_activity_at": "2013-09-30T13:46:02Z",
- "creator_id": 3,
- "namespace": {
- "created_at": "2013-09-30T13:46:02Z",
- "description": "",
- "id": 3,
- "name": "Diaspora",
- "owner_id": 1,
- "path": "diaspora",
- "updated_at": "2013-09-30T13:46:02Z"
- },
- "archived": false,
- "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png",
- "shared_runners_enabled": true,
- "forks_count": 0,
- "star_count": 0,
- "runners_token": "b8547b1dc37721d05889db52fa2f02",
- "public_builds": true,
- "shared_with_groups": []
- },
- {
- "id": 6,
- "description": null,
- "default_branch": "master",
- "public": false,
- "visibility_level": 0,
- "ssh_url_to_repo": "git@example.com:brightbox/puppet.git",
- "http_url_to_repo": "http://example.com/brightbox/puppet.git",
- "web_url": "http://example.com/brightbox/puppet",
- "tag_list": [
- "example",
- "puppet"
- ],
- "owner": {
- "id": 4,
- "name": "Brightbox",
- "created_at": "2013-09-30T13:46:02Z"
- },
- "name": "Puppet",
- "name_with_namespace": "Brightbox / Puppet",
- "path": "puppet",
- "path_with_namespace": "brightbox/puppet",
- "issues_enabled": true,
- "open_issues_count": 1,
- "merge_requests_enabled": true,
- "builds_enabled": true,
- "wiki_enabled": true,
- "snippets_enabled": false,
- "container_registry_enabled": false,
- "created_at": "2013-09-30T13:46:02Z",
- "last_activity_at": "2013-09-30T13:46:02Z",
- "creator_id": 3,
- "namespace": {
- "created_at": "2013-09-30T13:46:02Z",
- "description": "",
- "id": 4,
- "name": "Brightbox",
- "owner_id": 1,
- "path": "brightbox",
- "updated_at": "2013-09-30T13:46:02Z"
- },
- "permissions": {
- "project_access": {
- "access_level": 10,
- "notification_level": 3
- },
- "group_access": {
- "access_level": 50,
- "notification_level": 3
- }
- },
- "archived": false,
- "avatar_url": null,
- "shared_runners_enabled": true,
- "forks_count": 0,
- "star_count": 0,
- "runners_token": "b8547b1dc37721d05889db52fa2f02",
- "public_builds": true,
- "shared_with_groups": []
+ "only_allow_merge_if_pipeline_succeeds": false,
+ "only_allow_merge_if_all_discussions_are_resolved": false,
+ "request_access_enabled": false,
+ "statistics": {
+ "commit_count": 12,
+ "storage_size": 2066080,
+ "repository_size": 2066080,
+ "lfs_objects_size": 0,
+ "job_artifacts_size": 0
+ }
}
]
```
-### List owned projects
-
-Get a list of projects which are owned by the authenticated user.
-
-```
-GET /projects/owned
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `archived` | boolean | no | Limit by archived status |
-| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
-| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at` |
-| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
-| `search` | string | no | Return list of authorized projects matching the search criteria |
-
-### List starred projects
-
-Get a list of projects which are starred by the authenticated user.
-
-```
-GET /projects/starred
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `archived` | boolean | no | Limit by archived status |
-| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
-| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at` |
-| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
-| `search` | string | no | Return list of authorized projects matching the search criteria |
-
-### List ALL projects
-
-Get a list of all GitLab projects (admin only).
-
-```
-GET /projects/all
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `archived` | boolean | no | Limit by archived status |
-| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
-| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at` |
-| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
-| `search` | string | no | Return list of authorized projects matching the search criteria |
-
### Get single project
-Get a specific project, identified by project ID or NAMESPACE/PROJECT_NAME, which is owned by the authenticated user.
-If using namespaced projects call make sure that the NAMESPACE/PROJECT_NAME is URL-encoded, eg. `/api/v3/projects/diaspora%2Fdiaspora` (where `/` is represented by `%2F`).
+Get a specific project. This endpoint can be accessed without authentication if
+the project is publicly accessible.
```
GET /projects/:id
@@ -355,15 +186,15 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or NAMESPACE/PROJECT_NAME of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `statistics` | boolean | no | Include project statistics |
```json
{
"id": 3,
"description": null,
"default_branch": "master",
- "public": false,
- "visibility_level": 0,
+ "visibility": "private",
"ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git",
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
"web_url": "http://example.com/diaspora/diaspora-project-site",
@@ -383,7 +214,7 @@ Parameters:
"issues_enabled": true,
"open_issues_count": 1,
"merge_requests_enabled": true,
- "builds_enabled": true,
+ "jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"container_registry_enabled": false,
@@ -391,14 +222,14 @@ Parameters:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
- "created_at": "2013-09-30T13:46:02Z",
- "description": "",
"id": 3,
"name": "Diaspora",
- "owner_id": 1,
"path": "diaspora",
- "updated_at": "2013-09-30T13:46:02Z"
+ "kind": "group",
+ "full_path": "diaspora"
},
+ "import_status": "none",
+ "import_error": null,
"permissions": {
"project_access": {
"access_level": 10,
@@ -415,7 +246,7 @@ Parameters:
"forks_count": 0,
"star_count": 0,
"runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
- "public_builds": true,
+ "public_jobs": true,
"shared_with_groups": [
{
"group_id": 4,
@@ -428,152 +259,60 @@ Parameters:
"group_access_level": 10
}
],
- "only_allow_merge_if_build_succeeds": false,
- "request_access_enabled": false
+ "only_allow_merge_if_pipeline_succeeds": false,
+ "only_allow_merge_if_all_discussions_are_resolved": false,
+ "printing_merge_requests_link_enabled": true,
+ "request_access_enabled": false,
+ "statistics": {
+ "commit_count": 37,
+ "storage_size": 1038090,
+ "repository_size": 1038090,
+ "lfs_objects_size": 0,
+ "job_artifacts_size": 0
+ }
}
```
-### Get project events
+## Get project users
-Get the events for the specified project.
-Sorted from newest to latest
+Get the users list of a project.
-```
-GET /projects/:id/events
-```
Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or NAMESPACE/PROJECT_NAME of the project |
+| `search` | string | no | Search for specific users |
+
+```
+GET /projects/:id/users
+```
```json
[
{
- "title": null,
- "project_id": 15,
- "action_name": "closed",
- "target_id": 830,
- "target_type": "Issue",
- "author_id": 1,
- "data": null,
- "target_title": "Public project search field",
- "author": {
- "name": "Dmitriy Zaporozhets",
- "username": "root",
- "id": 1,
- "state": "active",
- "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
- "web_url": "http://localhost:3000/u/root"
- },
- "author_username": "root"
- },
- {
- "title": null,
- "project_id": 15,
- "action_name": "opened",
- "target_id": null,
- "target_type": null,
- "author_id": 1,
- "author": {
- "name": "Dmitriy Zaporozhets",
- "username": "root",
- "id": 1,
- "state": "active",
- "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
- "web_url": "http://localhost:3000/u/root"
- },
- "author_username": "john",
- "data": {
- "before": "50d4420237a9de7be1304607147aec22e4a14af7",
- "after": "c5feabde2d8cd023215af4d2ceeb7a64839fc428",
- "ref": "refs/heads/master",
- "user_id": 1,
- "user_name": "Dmitriy Zaporozhets",
- "repository": {
- "name": "gitlabhq",
- "url": "git@dev.gitlab.org:gitlab/gitlabhq.git",
- "description": "GitLab: self hosted Git management software. \r\nDistributed under the MIT License.",
- "homepage": "https://dev.gitlab.org/gitlab/gitlabhq"
- },
- "commits": [
- {
- "id": "c5feabde2d8cd023215af4d2ceeb7a64839fc428",
- "message": "Add simple search to projects in public area",
- "timestamp": "2013-05-13T18:18:08+00:00",
- "url": "https://dev.gitlab.org/gitlab/gitlabhq/commit/c5feabde2d8cd023215af4d2ceeb7a64839fc428",
- "author": {
- "name": "Dmitriy Zaporozhets",
- "email": "dmitriy.zaporozhets@gmail.com"
- }
- }
- ],
- "total_commits_count": 1
- },
- "target_title": null
+ "id": 1,
+ "username": "john_smith",
+ "name": "John Smith",
+ "state": "active",
+ "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg",
+ "web_url": "http://localhost:3000/john_smith"
},
{
- "title": null,
- "project_id": 15,
- "action_name": "closed",
- "target_id": 840,
- "target_type": "Issue",
- "author_id": 1,
- "data": null,
- "target_title": "Finish & merge Code search PR",
- "author": {
- "name": "Dmitriy Zaporozhets",
- "username": "root",
- "id": 1,
- "state": "active",
- "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
- "web_url": "http://localhost:3000/u/root"
- },
- "author_username": "root"
- },
- {
- "title": null,
- "project_id": 15,
- "action_name": "commented on",
- "target_id": 1312,
- "target_type": "Note",
- "author_id": 1,
- "data": null,
- "target_title": null,
- "created_at": "2015-12-04T10:33:58.089Z",
- "note": {
- "id": 1312,
- "body": "What an awesome day!",
- "attachment": null,
- "author": {
- "name": "Dmitriy Zaporozhets",
- "username": "root",
- "id": 1,
- "state": "active",
- "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
- "web_url": "http://localhost:3000/u/root"
- },
- "created_at": "2015-12-04T10:33:56.698Z",
- "system": false,
- "upvote": false,
- "downvote": false,
- "noteable_id": 377,
- "noteable_type": "Issue"
- },
- "author": {
- "name": "Dmitriy Zaporozhets",
- "username": "root",
- "id": 1,
- "state": "active",
- "avatar_url": "http://localhost:3000/uploads/user/avatar/1/fox_avatar.png",
- "web_url": "http://localhost:3000/u/root"
- },
- "author_username": "root"
+ "id": 2,
+ "username": "jack_smith",
+ "name": "Jack Smith",
+ "state": "blocked",
+ "avatar_url": "http://gravatar.com/../e32131cd8.jpeg",
+ "web_url": "http://localhost:3000/jack_smith"
}
]
```
+### Get project events
+
+Please refer to the [Events API documentation](events.md#list-a-projects-visible-events)
+
### Create project
Creates a new project owned by the authenticated user.
@@ -586,24 +325,27 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `name` | string | yes | The name of the new project |
-| `path` | string | no | Custom repository name for new project. By default generated based on name |
+| `name` | string | yes if path is not provided | The name of the new project. Equals path if not provided. |
+| `path` | string | yes if name is not provided | Repository name for new project. Generated based on name if not provided (generated lowercased with dashes). |
| `namespace_id` | integer | no | Namespace for the new project (defaults to the current user's namespace) |
| `description` | string | no | Short project description |
| `issues_enabled` | boolean | no | Enable issues for this project |
| `merge_requests_enabled` | boolean | no | Enable merge requests for this project |
-| `builds_enabled` | boolean | no | Enable builds for this project |
+| `jobs_enabled` | boolean | no | Enable jobs for this project |
| `wiki_enabled` | boolean | no | Enable wiki for this project |
| `snippets_enabled` | boolean | no | Enable snippets for this project |
| `container_registry_enabled` | boolean | no | Enable container registry for this project |
| `shared_runners_enabled` | boolean | no | Enable shared runners for this project |
-| `public` | boolean | no | If `true`, the same as setting `visibility_level` to 20 |
-| `visibility_level` | integer | no | See [project visibility level][#project-visibility-level] |
+| `visibility` | String | no | See [project visibility level](#project-visibility-level) |
| `import_url` | string | no | URL to import repository from |
-| `public_builds` | boolean | no | If `true`, builds can be viewed by non-project-members |
-| `only_allow_merge_if_build_succeeds` | boolean | no | Set whether merge requests can only be merged with successful builds |
+| `public_jobs` | boolean | no | If `true`, jobs can be viewed by non-project-members |
+| `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs |
+| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved |
| `lfs_enabled` | boolean | no | Enable LFS |
| `request_access_enabled` | boolean | no | Allow users to request member access |
+| `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project |
+| `avatar` | mixed | no | Image file for avatar of the project |
+| `printing_merge_request_link_enabled` | boolean | no | Show link to create/view merge request when pushing from the command line |
| `ci_config_file` | boolean | no | The relative path to the CI config file (E.g. my/path or my/path/.gitlab-ci.yml or my/path/my-config.yml) |
### Create project for user
@@ -621,27 +363,31 @@ Parameters:
| `user_id` | integer | yes | The user ID of the project owner |
| `name` | string | yes | The name of the new project |
| `path` | string | no | Custom repository name for new project. By default generated based on name |
+| `default_branch` | string | no | `master` by default |
| `namespace_id` | integer | no | Namespace for the new project (defaults to the current user's namespace) |
| `description` | string | no | Short project description |
| `issues_enabled` | boolean | no | Enable issues for this project |
| `merge_requests_enabled` | boolean | no | Enable merge requests for this project |
-| `builds_enabled` | boolean | no | Enable builds for this project |
+| `jobs_enabled` | boolean | no | Enable jobs for this project |
| `wiki_enabled` | boolean | no | Enable wiki for this project |
| `snippets_enabled` | boolean | no | Enable snippets for this project |
| `container_registry_enabled` | boolean | no | Enable container registry for this project |
| `shared_runners_enabled` | boolean | no | Enable shared runners for this project |
-| `public` | boolean | no | If `true`, the same as setting `visibility_level` to 20 |
-| `visibility_level` | integer | no | See [project visibility level][#project-visibility-level] |
+| `visibility` | string | no | See [project visibility level](#project-visibility-level) |
| `import_url` | string | no | URL to import repository from |
-| `public_builds` | boolean | no | If `true`, builds can be viewed by non-project-members |
-| `only_allow_merge_if_build_succeeds` | boolean | no | Set whether merge requests can only be merged with successful builds |
+| `public_jobs` | boolean | no | If `true`, jobs can be viewed by non-project-members |
+| `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs |
+| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved |
| `lfs_enabled` | boolean | no | Enable LFS |
| `request_access_enabled` | boolean | no | Allow users to request member access |
+| `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project |
+| `avatar` | mixed | no | Image file for avatar of the project |
+| `printing_merge_request_link_enabled` | boolean | no | Show link to create/view merge request when pushing from the command line |
| `ci_config_file` | boolean | no | The relative path to the CI config file (E.g. my/path or my/path/.gitlab-ci.yml or my/path/my-config.yml) |
### Edit project
-Updates an existing project
+Updates an existing project.
```
PUT /projects/:id
@@ -651,48 +397,49 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or NAMESPACE/PROJECT_NAME of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `name` | string | yes | The name of the project |
| `path` | string | no | Custom repository name for the project. By default generated based on name |
+| `default_branch` | string | no | `master` by default |
| `description` | string | no | Short project description |
| `issues_enabled` | boolean | no | Enable issues for this project |
| `merge_requests_enabled` | boolean | no | Enable merge requests for this project |
-| `builds_enabled` | boolean | no | Enable builds for this project |
+| `jobs_enabled` | boolean | no | Enable jobs for this project |
| `wiki_enabled` | boolean | no | Enable wiki for this project |
| `snippets_enabled` | boolean | no | Enable snippets for this project |
| `container_registry_enabled` | boolean | no | Enable container registry for this project |
| `shared_runners_enabled` | boolean | no | Enable shared runners for this project |
-| `public` | boolean | no | If `true`, the same as setting `visibility_level` to 20 |
-| `visibility_level` | integer | no | See [project visibility level][#project-visibility-level] |
+| `visibility` | string | no | See [project visibility level](#project-visibility-level) |
| `import_url` | string | no | URL to import repository from |
-| `public_builds` | boolean | no | If `true`, builds can be viewed by non-project-members |
-| `only_allow_merge_if_build_succeeds` | boolean | no | Set whether merge requests can only be merged with successful builds |
+| `public_jobs` | boolean | no | If `true`, jobs can be viewed by non-project-members |
+| `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs |
+| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved |
| `lfs_enabled` | boolean | no | Enable LFS |
| `request_access_enabled` | boolean | no | Allow users to request member access |
+| `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project |
+| `avatar` | mixed | no | Image file for avatar of the project |
| `ci_config_file` | boolean | no | The relative path to the CI config file (E.g. my/path or my/path/.gitlab-ci.yml or my/path/my-config.yml) |
-On success, method returns 200 with the updated project. If parameters are
-invalid, 400 is returned.
-
### Fork project
Forks a project into the user namespace of the authenticated user or the one provided.
+The forking operation for a project is asynchronous and is completed in a background job. The request will return immediately. To determine whether the fork of the project has completed, query the `import_status` for the new project.
+
```
-POST /projects/fork/:id
+POST /projects/:id/fork
```
Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or NAMESPACE/PROJECT_NAME of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `namespace` | integer/string | yes | The ID or path of the namespace that the project will be forked to |
### Star a project
-Stars a given project. Returns status code `201` and the project on success and
-`304` if the project is already starred.
+Stars a given project. Returns status code `304` if the project is already starred.
```
POST /projects/:id/star
@@ -702,10 +449,10 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or NAMESPACE/PROJECT_NAME of the project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/star"
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/star"
```
Example response:
@@ -715,8 +462,7 @@ Example response:
"id": 3,
"description": null,
"default_branch": "master",
- "public": false,
- "visibility_level": 10,
+ "visibility": "internal",
"ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git",
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
"web_url": "http://example.com/diaspora/diaspora-project-site",
@@ -731,7 +477,7 @@ Example response:
"issues_enabled": true,
"open_issues_count": 1,
"merge_requests_enabled": true,
- "builds_enabled": true,
+ "jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"container_registry_enabled": false,
@@ -739,41 +485,40 @@ Example response:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
- "created_at": "2013-09-30T13:46:02Z",
- "description": "",
"id": 3,
"name": "Diaspora",
- "owner_id": 1,
"path": "diaspora",
- "updated_at": "2013-09-30T13:46:02Z"
+ "kind": "group",
+ "full_path": "diaspora"
},
+ "import_status": "none",
"archived": true,
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
"shared_runners_enabled": true,
"forks_count": 0,
"star_count": 1,
- "public_builds": true,
+ "public_jobs": true,
"shared_with_groups": [],
- "only_allow_merge_if_build_succeeds": false,
+ "only_allow_merge_if_pipeline_succeeds": false,
+ "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false
}
```
### Unstar a project
-Unstars a given project. Returns status code `200` and the project on success
-and `304` if the project is not starred.
+Unstars a given project. Returns status code `304` if the project is not starred.
```
-DELETE /projects/:id/star
+POST /projects/:id/unstar
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/5/star"
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/unstar"
```
Example response:
@@ -783,8 +528,7 @@ Example response:
"id": 3,
"description": null,
"default_branch": "master",
- "public": false,
- "visibility_level": 10,
+ "visibility": "internal",
"ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git",
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
"web_url": "http://example.com/diaspora/diaspora-project-site",
@@ -799,7 +543,7 @@ Example response:
"issues_enabled": true,
"open_issues_count": 1,
"merge_requests_enabled": true,
- "builds_enabled": true,
+ "jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"container_registry_enabled": false,
@@ -807,22 +551,22 @@ Example response:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
- "created_at": "2013-09-30T13:46:02Z",
- "description": "",
"id": 3,
"name": "Diaspora",
- "owner_id": 1,
"path": "diaspora",
- "updated_at": "2013-09-30T13:46:02Z"
+ "kind": "group",
+ "full_path": "diaspora"
},
+ "import_status": "none",
"archived": true,
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
"shared_runners_enabled": true,
"forks_count": 0,
"star_count": 0,
- "public_builds": true,
+ "public_jobs": true,
"shared_with_groups": [],
- "only_allow_merge_if_build_succeeds": false,
+ "only_allow_merge_if_pipeline_succeeds": false,
+ "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false
}
```
@@ -832,20 +576,16 @@ Example response:
Archives the project if the user is either admin or the project owner of this project. This action is
idempotent, thus archiving an already archived project will not change the project.
-Status code 201 with the project as body is given when successful, in case the user doesn't
-have the proper access rights, code 403 is returned. Status 404 is returned if the project
-doesn't exist, or is hidden to the user.
-
```
POST /projects/:id/archive
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/archive"
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/archive"
```
Example response:
@@ -855,8 +595,7 @@ Example response:
"id": 3,
"description": null,
"default_branch": "master",
- "public": false,
- "visibility_level": 0,
+ "visibility": "private",
"ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git",
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
"web_url": "http://example.com/diaspora/diaspora-project-site",
@@ -876,7 +615,7 @@ Example response:
"issues_enabled": true,
"open_issues_count": 1,
"merge_requests_enabled": true,
- "builds_enabled": true,
+ "jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"container_registry_enabled": false,
@@ -884,14 +623,14 @@ Example response:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
- "created_at": "2013-09-30T13:46:02Z",
- "description": "",
"id": 3,
"name": "Diaspora",
- "owner_id": 1,
"path": "diaspora",
- "updated_at": "2013-09-30T13:46:02Z"
+ "kind": "group",
+ "full_path": "diaspora"
},
+ "import_status": "none",
+ "import_error": null,
"permissions": {
"project_access": {
"access_level": 10,
@@ -908,9 +647,10 @@ Example response:
"forks_count": 0,
"star_count": 0,
"runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
- "public_builds": true,
+ "public_jobs": true,
"shared_with_groups": [],
- "only_allow_merge_if_build_succeeds": false,
+ "only_allow_merge_if_pipeline_succeeds": false,
+ "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false
}
```
@@ -920,20 +660,16 @@ Example response:
Unarchives the project if the user is either admin or the project owner of this project. This action is
idempotent, thus unarchiving an non-archived project will not change the project.
-Status code 201 with the project as body is given when successful, in case the user doesn't
-have the proper access rights, code 403 is returned. Status 404 is returned if the project
-doesn't exist, or is hidden to the user.
-
```
POST /projects/:id/unarchive
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/unarchive"
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/unarchive"
```
Example response:
@@ -943,8 +679,7 @@ Example response:
"id": 3,
"description": null,
"default_branch": "master",
- "public": false,
- "visibility_level": 0,
+ "visibility": "private",
"ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git",
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
"web_url": "http://example.com/diaspora/diaspora-project-site",
@@ -964,7 +699,7 @@ Example response:
"issues_enabled": true,
"open_issues_count": 1,
"merge_requests_enabled": true,
- "builds_enabled": true,
+ "jobs_enabled": true,
"wiki_enabled": true,
"snippets_enabled": false,
"container_registry_enabled": false,
@@ -972,14 +707,14 @@ Example response:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
- "created_at": "2013-09-30T13:46:02Z",
- "description": "",
"id": 3,
"name": "Diaspora",
- "owner_id": 1,
"path": "diaspora",
- "updated_at": "2013-09-30T13:46:02Z"
+ "kind": "group",
+ "full_path": "diaspora"
},
+ "import_status": "none",
+ "import_error": null,
"permissions": {
"project_access": {
"access_level": 10,
@@ -996,9 +731,10 @@ Example response:
"forks_count": 0,
"star_count": 0,
"runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
- "public_builds": true,
+ "public_jobs": true,
"shared_with_groups": [],
- "only_allow_merge_if_build_succeeds": false,
+ "only_allow_merge_if_pipeline_succeeds": false,
+ "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false
}
```
@@ -1015,7 +751,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
## Uploads
@@ -1031,9 +767,20 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `file` | string | yes | The file to be uploaded |
+To upload a file from your filesystem, use the `--form` argument. This causes
+cURL to post data using the header `Content-Type: multipart/form-data`.
+The `file=` parameter must point to a file on your filesystem and be preceded
+by `@`. For example:
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "file=@dk.png" https://gitlab.example.com/api/v3/projects/5/uploads
+```
+
+Returned object:
+
```json
{
"alt": "dk",
@@ -1043,8 +790,8 @@ Parameters:
```
**Note**: The returned `url` is relative to the project path.
-In Markdown contexts, the link is automatically expanded when the format in `markdown` is used.
-
+In Markdown contexts, the link is automatically expanded when the format in
+`markdown` is used.
## Project members
@@ -1062,11 +809,30 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `group_id` | integer | yes | The ID of the group to share with |
| `group_access` | integer | yes | The permissions level to grant the group |
| `expires_at` | string | no | Share expiration date in ISO 8601 format: 2016-09-26 |
+### Delete a shared project link within a group
+
+Unshare the project from the group. Returns `204` and no content on success.
+
+```
+DELETE /projects/:id/share/:group_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `group_id` | integer | yes | The ID of the group |
+
+```bash
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/share/17
+```
+
## Hooks
Also called Project Hooks and Webhooks.
@@ -1084,7 +850,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
### Get project hook
@@ -1098,7 +864,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `hook_id` | integer | yes | The ID of a project hook |
```json
@@ -1111,7 +877,7 @@ Parameters:
"merge_requests_events": true,
"tag_push_events": true,
"note_events": true,
- "build_events": true,
+ "job_events": true,
"pipeline_events": true,
"wiki_page_events": true,
"enable_ssl_verification": true,
@@ -1131,17 +897,18 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `url` | string | yes | The hook URL |
| `push_events` | boolean | no | Trigger hook on push events |
| `issues_events` | boolean | no | Trigger hook on issues events |
| `merge_requests_events` | boolean | no | Trigger hook on merge requests events |
| `tag_push_events` | boolean | no | Trigger hook on tag push events |
| `note_events` | boolean | no | Trigger hook on note events |
-| `build_events` | boolean | no | Trigger hook on build events |
+| `job_events` | boolean | no | Trigger hook on job events |
| `pipeline_events` | boolean | no | Trigger hook on pipeline events |
| `wiki_events` | boolean | no | Trigger hook on wiki events |
| `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook |
+| `token` | string | no | Secret token to validate received payloads; this will not be returned in the response |
### Edit project hook
@@ -1155,7 +922,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `hook_id` | integer | yes | The ID of the project hook |
| `url` | string | yes | The hook URL |
| `push_events` | boolean | no | Trigger hook on push events |
@@ -1163,10 +930,11 @@ Parameters:
| `merge_requests_events` | boolean | no | Trigger hook on merge requests events |
| `tag_push_events` | boolean | no | Trigger hook on tag push events |
| `note_events` | boolean | no | Trigger hook on note events |
-| `build_events` | boolean | no | Trigger hook on build events |
+| `job_events` | boolean | no | Trigger hook on job events |
| `pipeline_events` | boolean | no | Trigger hook on pipeline events |
| `wiki_events` | boolean | no | Trigger hook on wiki events |
| `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook |
+| `token` | string | no | Secret token to validate received payloads; this will not be returned in the response |
### Delete project hook
@@ -1181,7 +949,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `hook_id` | integer | yes | The ID of the project hook |
Note the JSON response differs if the hook is available or not. If the project hook
@@ -1203,7 +971,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```json
[
@@ -1260,7 +1028,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `branch` | string | yes | The name of the branch |
| `developers_can_push` | boolean | no | Flag if developers can push to the branch |
| `developers_can_merge` | boolean | no | Flag if developers can merge to the branch |
@@ -1277,7 +1045,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `branch` | string | yes | The name of the branch |
### Unprotect single branch
@@ -1292,7 +1060,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `branch` | string | yes | The name of the branch |
## Admin fork relation
@@ -1309,7 +1077,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `forked_from_id` | ID | yes | The ID of the project that was forked from |
### Delete an existing forked from relationship
@@ -1322,11 +1090,13 @@ Parameter:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
## Search for projects by name
-Search for projects by name which are accessible to the authenticated user.
+Search for projects by name which are accessible to the authenticated user. This
+endpoint can be accessed without authentication if the project is publicly
+accessible.
```
GET /projects/search/:query
@@ -1336,8 +1106,20 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `query` (required) - A string contained in the project name
-| `per_page` (optional) - number of projects to return per page
-| `page` (optional) - the page to retrieve
-| `order_by` (optional) - Return requests ordered by `id`, `name`, `created_at` or `last_activity_at` fields
+| `query` | string | yes | A string contained in the project name |
+| `order_by` | string | no | Return requests ordered by `id`, `name`, `created_at` or `last_activity_at` fields |
| `sort` | string | no | Return requests sorted in `asc` or `desc` order |
+
+## Start the Housekeeping task for a Project
+
+>**Note:** This feature was introduced in GitLab 9.0
+
+```
+POST /projects/:id/housekeeping
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index b6cca5d4e2a..bccef924375 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -1,8 +1,11 @@
-# Repositories
+# Repositories API
## List repository tree
-Get a list of repository files and directories in a project.
+Get a list of repository files and directories in a project. This endpoint can
+be accessed without authentication if the repository is publicly accessible.
+
+This command provides essentially the same functionality as the `git ls-tree` command. For more information, see the section _Tree Objects_ in the [Git internals documentation](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects/#_tree_objects).
```
GET /projects/:id/repository/tree
@@ -10,54 +13,70 @@ GET /projects/:id/repository/tree
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `path` (optional) - The path inside repository. Used to get contend of subdirectories
-- `ref_name` (optional) - The name of a repository branch or tag or if not given the default branch
+- `ref` (optional) - The name of a repository branch or tag or if not given the default branch
+- `recursive` (optional) - Boolean value used to get a recursive tree (false by default)
```json
[
{
- "name": "assets",
+ "id": "a1e8f8d745cc87e3a9248358d9352bb7f9a0aeba",
+ "name": "html",
"type": "tree",
- "mode": "040000",
- "id": "6229c43a7e16fcc7e95f923f8ddadb8281d9c6c6"
+ "path": "files/html",
+ "mode": "040000"
},
{
- "name": "contexts",
+ "id": "4535904260b1082e14f867f7a24fd8c21495bde3",
+ "name": "images",
"type": "tree",
- "mode": "040000",
- "id": "faf1cdf33feadc7973118ca42d35f1e62977e91f"
+ "path": "files/images",
+ "mode": "040000"
},
{
- "name": "controllers",
+ "id": "31405c5ddef582c5a9b7a85230413ff90e2fe720",
+ "name": "js",
"type": "tree",
- "mode": "040000",
- "id": "95633e8d258bf3dfba3a5268fb8440d263218d74"
+ "path": "files/js",
+ "mode": "040000"
},
{
- "name": "Rakefile",
- "type": "blob",
- "mode": "100644",
- "id": "35b2f05cbb4566b71b34554cf184a9d0bd9d46d6"
+ "id": "cc71111cfad871212dc99572599a568bfe1e7e00",
+ "name": "lfs",
+ "type": "tree",
+ "path": "files/lfs",
+ "mode": "040000"
},
{
- "name": "VERSION",
- "type": "blob",
- "mode": "100644",
- "id": "803e4a4f3727286c3093c63870c2b6524d30ec4f"
+ "id": "fd581c619bf59cfdfa9c8282377bb09c2f897520",
+ "name": "markdown",
+ "type": "tree",
+ "path": "files/markdown",
+ "mode": "040000"
},
{
- "name": "config.ru",
+ "id": "23ea4d11a4bdd960ee5320c5cb65b5b3fdbc60db",
+ "name": "ruby",
+ "type": "tree",
+ "path": "files/ruby",
+ "mode": "040000"
+ },
+ {
+ "id": "7d70e02340bac451f281cecf0a980907974bd8be",
+ "name": "whitespace",
"type": "blob",
- "mode": "100644",
- "id": "dfd2d862237323aa599be31b473d70a8a817943b"
+ "path": "files/whitespace",
+ "mode": "100644"
}
]
```
-## Raw file content
+## Get a blob from repository
-Get the raw file contents for a file by commit SHA and path.
+Allows you to receive information about blob in repository like size and
+content. Note that blob content is Base64 encoded. This endpoint can be accessed
+without authentication if the repository is publicly accessible.
```
GET /projects/:id/repository/blobs/:sha
@@ -65,26 +84,27 @@ GET /projects/:id/repository/blobs/:sha
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `sha` (required) - The commit or branch name
-- `filepath` (required) - The path the file
## Raw blob content
-Get the raw file contents for a blob by blob SHA.
+Get the raw file contents for a blob by blob SHA. This endpoint can be accessed
+without authentication if the repository is publicly accessible.
```
-GET /projects/:id/repository/raw_blobs/:sha
+GET /projects/:id/repository/blobs/:sha/raw
```
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `sha` (required) - The blob SHA
## Get file archive
-Get an archive of the repository
+Get an archive of the repository. This endpoint can be accessed without
+authentication if the repository is publicly accessible.
```
GET /projects/:id/repository/archive
@@ -92,18 +112,21 @@ GET /projects/:id/repository/archive
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `sha` (optional) - The commit SHA to download defaults to the tip of the default branch
## Compare branches, tags or commits
+This endpoint can be accessed without authentication if the repository is
+publicly accessible.
+
```
GET /projects/:id/repository/compare
```
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `from` (required) - the commit SHA or branch name
- `to` (required) - the commit SHA or branch name
@@ -149,7 +172,8 @@ Response:
## Contributors
-Get repository contributors list
+Get repository contributors list. This endpoint can be accessed without
+authentication if the repository is publicly accessible.
```
GET /projects/:id/repository/contributors
@@ -157,7 +181,7 @@ GET /projects/:id/repository/contributors
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
Response:
diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md
index 1bc6a24e914..18ceb8f779e 100644
--- a/doc/api/repository_files.md
+++ b/doc/api/repository_files.md
@@ -1,4 +1,4 @@
-# Repository files
+# Repository files API
**CRUD for repository files**
@@ -6,14 +6,16 @@
## Get file from repository
-Allows you to receive information about file in repository like name, size, content. Note that file content is Base64 encoded.
+Allows you to receive information about file in repository like name, size,
+content. Note that file content is Base64 encoded. This endpoint can be accessed
+without authentication if the repository is publicly accessible.
```
-GET /projects/:id/repository/files
+GET /projects/:id/repository/files/:file_path
```
```bash
-curl --request GET --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v3/projects/13083/repository/files?file_path=app/models/key.rb&ref=master'
+curl --request GET --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master'
```
Example response:
@@ -34,17 +36,32 @@ Example response:
Parameters:
-- `file_path` (required) - Full path to new file. Ex. lib/class.rb
+- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
+- `ref` (required) - The name of branch, tag or commit
+
+## Get raw file from repository
+
+```
+GET /projects/:id/repository/files/:file_path/raw
+```
+
+```bash
+curl --request GET --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb/raw?ref=master'
+```
+
+Parameters:
+
+- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
- `ref` (required) - The name of branch, tag or commit
## Create new file in repository
```
-POST /projects/:id/repository/files
+POST /projects/:id/repository/files/:file_path
```
```bash
-curl --request POST --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v3/projects/13083/repository/files?file_path=app/project.rb&branch_name=master&author_email=author%40example.com&author_name=Firstname%20Lastname&content=some%20content&commit_message=create%20a%20new%20file'
+curl --request POST --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v4/projects/13083/repository/app%2Fprojectrb%2E?branch=master&author_email=author%40example.com&author_name=Firstname%20Lastname&content=some%20content&commit_message=create%20a%20new%20file'
```
Example response:
@@ -52,15 +69,15 @@ Example response:
```json
{
"file_name": "app/project.rb",
- "branch_name": "master"
+ "branch": "master"
}
```
Parameters:
-- `file_path` (required) - Full path to new file. Ex. lib/class.rb
-- `branch_name` (required) - The name of branch
-- `encoding` (optional) - 'text' or 'base64'. Text is default.
+- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
+- `branch` (required) - The name of branch
+- `encoding` (optional) - Change encoding to 'base64'. Default is text.
- `author_email` (optional) - Specify the commit author's email address
- `author_name` (optional) - Specify the commit author's name
- `content` (required) - File content
@@ -69,11 +86,11 @@ Parameters:
## Update existing file in repository
```
-PUT /projects/:id/repository/files
+PUT /projects/:id/repository/files/:file_path
```
```bash
-curl --request PUT --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v3/projects/13083/repository/files?file_path=app/project.rb&branch_name=master&author_email=author%40example.com&author_name=Firstname%20Lastname&content=some%20other%20content&commit_message=update%20file'
+curl --request PUT --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v4/projects/13083/repository/app%2Fproject%2Erb?branch=master&author_email=author%40example.com&author_name=Firstname%20Lastname&content=some%20other%20content&commit_message=update%20file'
```
Example response:
@@ -81,19 +98,20 @@ Example response:
```json
{
"file_name": "app/project.rb",
- "branch_name": "master"
+ "branch": "master"
}
```
Parameters:
-- `file_path` (required) - Full path to file. Ex. lib/class.rb
-- `branch_name` (required) - The name of branch
-- `encoding` (optional) - 'text' or 'base64'. Text is default.
+- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
+- `branch` (required) - The name of branch
+- `encoding` (optional) - Change encoding to 'base64'. Default is text.
- `author_email` (optional) - Specify the commit author's email address
- `author_name` (optional) - Specify the commit author's name
- `content` (required) - New file content
- `commit_message` (required) - Commit message
+- `last_commit_id` (optional) - Last known file commit id
If the commit fails for any reason we return a 400 error with a non-specific
error message. Possible causes for a failed commit include:
@@ -107,11 +125,11 @@ Currently gitlab-shell has a boolean return code, preventing GitLab from specify
## Delete existing file in repository
```
-DELETE /projects/:id/repository/files
+DELETE /projects/:id/repository/files/:file_path
```
```bash
-curl --request PUT --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v3/projects/13083/repository/files?file_path=app/project.rb&branch_name=master&author_email=author%40example.com&author_name=Firstname%20Lastname&commit_message=delete%20file'
+curl --request DELETE --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v4/projects/13083/repository/app%2Fproject%2Erb?branch=master&author_email=author%40example.com&author_name=Firstname%20Lastname&commit_message=delete%20file'
```
Example response:
@@ -119,14 +137,14 @@ Example response:
```json
{
"file_name": "app/project.rb",
- "branch_name": "master"
+ "branch": "master"
}
```
Parameters:
-- `file_path` (required) - Full path to file. Ex. lib/class.rb
-- `branch_name` (required) - The name of branch
+- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
+- `branch` (required) - The name of branch
- `author_email` (optional) - Specify the commit author's email address
- `author_name` (optional) - Specify the commit author's name
- `commit_message` (required) - Commit message
diff --git a/doc/api/runners.md b/doc/api/runners.md
index 28610762dca..16d362a3530 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -18,7 +18,7 @@ GET /runners?scope=active
| `scope` | string | no | The scope of specific runners to show, one of: `active`, `paused`, `online`; showing all runners if none provided |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/runners"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners"
```
Example response:
@@ -57,7 +57,7 @@ GET /runners/all?scope=online
| `scope` | string | no | The scope of runners to show, one of: `specific`, `shared`, `active`, `paused`, `online`; showing all runners if none provided |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/runners/all"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners/all"
```
Example response:
@@ -108,7 +108,7 @@ GET /runners/:id
| `id` | integer | yes | The ID of a runner |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/runners/6"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners/6"
```
Example response:
@@ -158,7 +158,7 @@ PUT /runners/:id
| `tag_list` | array | no | The list of tags for a runner; put array of tags, that should be finally assigned to a runner |
```
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/runners/6" --form "description=test-1-20150125-test" --form "tag_list=ruby,mysql,tag1,tag2"
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners/6" --form "description=test-1-20150125-test" --form "tag_list=ruby,mysql,tag1,tag2"
```
Example response:
@@ -207,19 +207,7 @@ DELETE /runners/:id
| `id` | integer | yes | The ID of a runner |
```
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/runners/6"
-```
-
-Example response:
-
-```json
-{
- "active": true,
- "description": "test-1-20150125-test",
- "id": 6,
- "is_shared": false,
- "name": null,
-}
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners/6"
```
## List project's runners
@@ -234,10 +222,10 @@ GET /projects/:id/runners
| Attribute | Type | Required | Description |
|-----------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/9/runners"
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/9/runners"
```
Example response:
@@ -271,11 +259,11 @@ POST /projects/:id/runners
| Attribute | Type | Required | Description |
|-------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `runner_id` | integer | yes | The ID of a runner |
```
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/9/runners" --form "runner_id=9"
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/9/runners" --form "runner_id=9"
```
Example response:
@@ -302,21 +290,9 @@ DELETE /projects/:id/runners/:runner_id
| Attribute | Type | Required | Description |
|-------------|---------|----------|---------------------|
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `runner_id` | integer | yes | The ID of a runner |
```
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/9/runners/9"
-```
-
-Example response:
-
-```json
-{
- "active": true,
- "description": "test-2016-02-01",
- "id": 9,
- "is_shared": false,
- "name": null
-}
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/9/runners/9"
```
diff --git a/doc/api/services.md b/doc/api/services.md
index 579fdc0c8c9..49b87a4228c 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -1,4 +1,4 @@
-# Services
+# Services API
## Asana
@@ -451,41 +451,171 @@ GET /projects/:id/services/irker
## JIRA
-Jira issue tracker
+JIRA issue tracker.
+
+### Get JIRA service settings
+
+Get JIRA service settings for a project.
+
+```
+GET /projects/:id/services/jira
+```
### Create/Edit JIRA service
Set JIRA service for a project.
-> Setting `project_url`, `issues_url` and `new_issue_url` will allow a user to easily navigate to the Jira issue tracker. See the [integration doc](http://docs.gitlab.com/ce/integration/external-issue-tracker.html) for details. Support for referencing commits and automatic closing of Jira issues directly from GitLab is [available in GitLab EE.](http://docs.gitlab.com/ee/integration/jira.html)
+>**Notes:**
+- Starting with GitLab 8.14, `api_url`, `issues_url`, `new_issue_url` and
+ `project_url` are replaced by `project_key`, `url`. If you are using an
+ older version, [follow this documentation][old-jira-api].
```
PUT /projects/:id/services/jira
```
-Parameters:
-
-- `new_issue_url` (**required**) - New Issue url
-- `project_url` (**required**) - Project url
-- `issues_url` (**required**) - Issue url
-- `description` (optional) - Jira issue tracker
-- `username` (optional) - Jira username
-- `password` (optional) - Jira password
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `url` | string | yes | The URL to the JIRA project which is being linked to this GitLab project, e.g., `https://jira.example.com`. |
+| `project_key` | string | yes | The short identifier for your JIRA project, all uppercase, e.g., `PROJ`. |
+| `username` | string | no | The username of the user created to be used with GitLab/JIRA. |
+| `password` | string | no | The password of the user created to be used with GitLab/JIRA. |
+| `jira_issue_transition_id` | integer | no | The ID of a transition that moves issues to a closed state. You can find this number under the JIRA workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column ([see screenshot][trans]). By default, this ID is set to `2`. |
### Delete JIRA service
-Delete JIRA service for a project.
+Remove all previously JIRA settings from a project.
```
DELETE /projects/:id/services/jira
```
-### Get JIRA service settings
+## Slack slash commands
-Get JIRA service settings for a project.
+Ability to receive slash commands from a Slack chat instance.
+
+### Get Slack slash command service settings
+
+Get Slack slash command service settings for a project.
```
-GET /projects/:id/services/jira
+GET /projects/:id/services/slack-slash-commands
+```
+
+Example response:
+
+```json
+{
+ "id": 4,
+ "title": "Slack slash commands",
+ "created_at": "2017-06-27T05:51:39-07:00",
+ "updated_at": "2017-06-27T05:51:39-07:00",
+ "active": true,
+ "push_events": true,
+ "issues_events": true,
+ "merge_requests_events": true,
+ "tag_push_events": true,
+ "note_events": true,
+ "job_events": true,
+ "pipeline_events": true,
+ "properties": {
+ "token": "9koXpg98eAheJpvBs5tK"
+ }
+}
+```
+
+### Create/Edit Slack slash command service
+
+Set Slack slash command for a project.
+
+```
+PUT /projects/:id/services/slack-slash-commands
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `token` | string | yes | The Slack token |
+
+
+### Delete Slack slash command service
+
+Delete Slack slash command service for a project.
+
+```
+DELETE /projects/:id/services/slack-slash-commands
+```
+
+## Mattermost slash commands
+
+Ability to receive slash commands from a Mattermost chat instance.
+
+### Get Mattermost slash command service settings
+
+Get Mattermost slash command service settings for a project.
+
+```
+GET /projects/:id/services/mattermost-slash-commands
+```
+
+### Create/Edit Mattermost slash command service
+
+Set Mattermost slash command for a project.
+
+```
+PUT /projects/:id/services/mattermost-slash-commands
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `token` | string | yes | The Mattermost token |
+
+
+### Delete Mattermost slash command service
+
+Delete Mattermost slash command service for a project.
+
+```
+DELETE /projects/:id/services/mattermost-slash-commands
+```
+
+## Pipeline-Emails
+
+Get emails for GitLab CI pipelines.
+
+### Create/Edit Pipeline-Emails service
+
+Set Pipeline-Emails service for a project.
+
+```
+PUT /projects/:id/services/pipelines-email
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `recipients` | string | yes | Comma-separated list of recipient email addresses |
+| `add_pusher` | boolean | no | Add pusher to recipients list |
+| `notify_only_broken_pipelines` | boolean | no | Notify only broken pipelines |
+
+### Delete Pipeline-Emails service
+
+Delete Pipeline-Emails service for a project.
+
+```
+DELETE /projects/:id/services/pipelines-email
+```
+
+### Get Pipeline-Emails service settings
+
+Get Pipeline-Emails service settings for a project.
+
+```
+GET /projects/:id/services/pipelines-email
```
## PivotalTracker
@@ -592,9 +722,9 @@ Get Redmine service settings for a project.
GET /projects/:id/services/redmine
```
-## Slack
+## Slack notifications
-A team communication tool for the 21st century
+Receive event notifications in Slack
### Create/Edit Slack service
@@ -626,6 +756,40 @@ Get Slack service settings for a project.
GET /projects/:id/services/slack
```
+## Mattermost notifications
+
+Receive event notifications in Mattermost
+
+### Create/Edit Mattermost notifications service
+
+Set Mattermost service for a project.
+
+```
+PUT /projects/:id/services/mattermost
+```
+
+Parameters:
+
+- `webhook` (**required**) - https://mattermost.example/hooks/1298aff...
+- `username` (optional) - username
+- `channel` (optional) - #channel
+
+### Delete Mattermost notifications service
+
+Delete Mattermost Notifications service for a project.
+
+```
+DELETE /projects/:id/services/mattermost
+```
+
+### Get Mattermost notifications service settings
+
+Get Mattermost notifications service settings for a project.
+
+```
+GET /projects/:id/services/mattermost
+```
+
## JetBrains TeamCity CI
A continuous integration and build server
@@ -662,3 +826,41 @@ Get JetBrains TeamCity CI service settings for a project.
```
GET /projects/:id/services/teamcity
```
+
+[jira-doc]: ../user/project/integrations/jira.md
+[old-jira-api]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-13-stable/doc/api/services.md#jira
+
+
+## MockCI
+
+Mock an external CI. See [`gitlab-org/gitlab-mock-ci-service`](https://gitlab.com/gitlab-org/gitlab-mock-ci-service) for an example of a companion mock service.
+
+This service is only available when your environment is set to development.
+
+### Create/Edit MockCI service
+
+Set MockCI service for a project.
+
+```
+PUT /projects/:id/services/mock-ci
+```
+
+Parameters:
+
+- `mock_service_url` (**required**) - http://localhost:4004
+
+### Delete MockCI service
+
+Delete MockCI service for a project.
+
+```
+DELETE /projects/:id/services/mock-ci
+```
+
+### Get MockCI service settings
+
+Get MockCI service settings for a project.
+
+```
+GET /projects/:id/services/mock-ci
+```
diff --git a/doc/api/session.md b/doc/api/session.md
index f776424023e..f79eac11689 100644
--- a/doc/api/session.md
+++ b/doc/api/session.md
@@ -1,11 +1,9 @@
-# Session
+# Session API
-## Deprecation Notice
-
-1. Starting in GitLab 8.11, this feature has been *disabled* for users with two-factor authentication turned on.
-2. These users can access the API using [personal access tokens] instead.
-
----
+>**Deprecation notice:**
+Starting in GitLab 8.11, this feature has been **disabled** for users with
+[two-factor authentication][2fa] turned on. These users can access the API
+using [personal access tokens] instead.
You can login with both GitLab and LDAP credentials in order to obtain the
private token.
@@ -21,7 +19,7 @@ POST /session
| `password` | string | yes | The password of the user |
```bash
-curl --request POST "https://gitlab.example.com/api/v3/session?login=john_smith&password=strongpassw0rd"
+curl --request POST "https://gitlab.example.com/api/v4/session?login=john_smith&password=strongpassw0rd"
```
Example response:
@@ -41,7 +39,6 @@ Example response:
"twitter": "",
"website_url": "",
"email": "john@example.com",
- "theme_id": 1,
"color_scheme_id": 1,
"projects_limit": 10,
"current_sign_in_at": "2015-07-07T07:10:58.392Z",
@@ -53,4 +50,5 @@ Example response:
}
```
-[personal access tokens]: ./README.md#personal-access-tokens
+[2fa]: ../user/profile/account/two_factor_authentication.md
+[personal access tokens]: ../user/profile/personal_access_tokens.md
diff --git a/doc/api/settings.md b/doc/api/settings.md
index f7ad3b4cc8e..eefbdda42ce 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -1,4 +1,4 @@
-# Application settings
+# Application settings API
These API calls allow you to read and modify GitLab instance application
settings as appear in `/admin/application_settings`. You have to be an
@@ -13,14 +13,14 @@ GET /application/settings
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/application/settings
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/application/settings
```
Example response:
```json
{
- "default_projects_limit" : 10,
+ "default_projects_limit" : 100000,
"signup_enabled" : true,
"id" : 1,
"default_branch_protection" : 2,
@@ -32,18 +32,24 @@ Example response:
"updated_at" : "2016-01-04T15:44:55.176Z",
"session_expire_delay" : 10080,
"home_page_url" : null,
- "default_snippet_visibility" : 0,
+ "default_snippet_visibility" : "private",
"domain_whitelist" : [],
"domain_blacklist_enabled" : false,
"domain_blacklist" : [],
"created_at" : "2016-01-04T15:44:55.176Z",
- "default_project_visibility" : 0,
+ "default_project_visibility" : "private",
+ "default_group_visibility" : "private",
"gravatar_enabled" : true,
"sign_in_text" : null,
"container_registry_token_expire_delay": 5,
"repository_storage": "default",
+ "repository_storages": ["default"],
"koding_enabled": false,
- "koding_url": null
+ "koding_url": null,
+ "plantuml_enabled": false,
+ "plantuml_url": null,
+ "terminal_max_session_time": 0,
+ "polling_interval_multiplier": 1.0
}
```
@@ -55,31 +61,38 @@ PUT /application/settings
| Attribute | Type | Required | Description |
| --------- | ---- | :------: | ----------- |
-| `default_projects_limit` | integer | no | Project limit per user. Default is `10` |
+| `default_projects_limit` | integer | no | Project limit per user. Default is `100000` |
| `signup_enabled` | boolean | no | Enable registration. Default is `true`. |
| `signin_enabled` | boolean | no | Enable login via a GitLab account. Default is `true`. |
| `gravatar_enabled` | boolean | no | Enable Gravatar |
| `sign_in_text` | string | no | Text on login page |
| `home_page_url` | string | no | Redirect to this URL when not logged in |
| `default_branch_protection` | integer | no | Determine if developers can push to master. Can take `0` _(not protected, both developers and masters can push new commits, force push or delete the branch)_, `1` _(partially protected, developers can push new commits, but cannot force push or delete the branch, masters can do anything)_ or `2` _(fully protected, developers cannot push new commits, force push or delete the branch, masters can do anything)_ as a parameter. Default is `2`. |
-| `restricted_visibility_levels` | array of integers | no | Selected levels cannot be used by non-admin users for projects or snippets. Can take `0` _(Private)_, `1` _(Internal)_ and `2` _(Public)_ as a parameter. Default is null which means there is no restriction. |
+| `restricted_visibility_levels` | array of strings | no | Selected levels cannot be used by non-admin users for projects or snippets. Can take `private`, `internal` and `public` as a parameter. Default is null which means there is no restriction. |
| `max_attachment_size` | integer | no | Limit attachment size in MB |
| `session_expire_delay` | integer | no | Session duration in minutes. GitLab restart is required to apply changes |
-| `default_project_visibility` | integer | no | What visibility level new projects receive. Can take `0` _(Private)_, `1` _(Internal)_ and `2` _(Public)_ as a parameter. Default is `0`.|
-| `default_snippet_visibility` | integer | no | What visibility level new snippets receive. Can take `0` _(Private)_, `1` _(Internal)_ and `2` _(Public)_ as a parameter. Default is `0`.|
+| `default_project_visibility` | string | no | What visibility level new projects receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`.|
+| `default_snippet_visibility` | string | no | What visibility level new snippets receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`.|
+| `default_group_visibility` | string | no | What visibility level new groups receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`.|
| `domain_whitelist` | array of strings | no | Force people to use only corporate emails for sign-up. Default is null, meaning there is no restriction. |
| `domain_blacklist_enabled` | boolean | no | Enable/disable the `domain_blacklist` |
| `domain_blacklist` | array of strings | yes (if `domain_blacklist_enabled` is `true`) | People trying to sign-up with emails from this domain will not be allowed to do so. |
| `user_oauth_applications` | boolean | no | Allow users to register any application to use GitLab as an OAuth provider |
| `after_sign_out_path` | string | no | Where to redirect users after logout |
| `container_registry_token_expire_delay` | integer | no | Container Registry token duration in minutes |
-| `repository_storage` | string | no | Storage path for new projects. The value should be the name of one of the repository storage paths defined in your gitlab.yml |
+| `repository_storages` | array of strings | no | A list of names of enabled storage paths, taken from `gitlab.yml`. New projects will be created in one of these stores, chosen at random. |
+| `repository_storage` | string | no | The first entry in `repository_storages`. Deprecated, but retained for compatibility reasons |
| `enabled_git_access_protocol` | string | no | Enabled protocols for Git access. Allowed values are: `ssh`, `http`, and `nil` to allow both protocols. |
| `koding_enabled` | boolean | no | Enable Koding integration. Default is `false`. |
| `koding_url` | string | yes (if `koding_enabled` is `true`) | The Koding instance URL for integration. |
+| `disabled_oauth_sign_in_sources` | Array of strings | no | Disabled OAuth sign-in sources |
+| `plantuml_enabled` | boolean | no | Enable PlantUML integration. Default is `false`. |
+| `plantuml_url` | string | yes (if `plantuml_enabled` is `true`) | The PlantUML instance URL for integration. |
+| `terminal_max_session_time` | integer | no | Maximum time for web terminal websocket connection (in seconds). Set to 0 for unlimited time. |
+| `polling_interval_multiplier` | decimal | no | Interval multiplier used by endpoints that perform polling. Set to 0 to disable polling. |
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/application/settings?signup_enabled=false&default_project_visibility=1
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/application/settings?signup_enabled=false&default_project_visibility=internal
```
Example response:
@@ -87,7 +100,7 @@ Example response:
```json
{
"id": 1,
- "default_projects_limit": 10,
+ "default_projects_limit": 100000,
"signup_enabled": true,
"signin_enabled": true,
"gravatar_enabled": true,
@@ -99,8 +112,9 @@ Example response:
"restricted_visibility_levels": [],
"max_attachment_size": 10,
"session_expire_delay": 10080,
- "default_project_visibility": 1,
- "default_snippet_visibility": 0,
+ "default_project_visibility": "internal",
+ "default_snippet_visibility": "private",
+ "default_group_visibility": "private",
"domain_whitelist": [],
"domain_blacklist_enabled" : false,
"domain_blacklist" : [],
@@ -109,6 +123,10 @@ Example response:
"container_registry_token_expire_delay": 5,
"repository_storage": "default",
"koding_enabled": false,
- "koding_url": null
+ "koding_url": null,
+ "plantuml_enabled": false,
+ "plantuml_url": null,
+ "terminal_max_session_time": 0,
+ "polling_interval_multiplier": 1.0
}
```
diff --git a/doc/api/sidekiq_metrics.md b/doc/api/sidekiq_metrics.md
index 1ae732d40d6..b9500916cf2 100644
--- a/doc/api/sidekiq_metrics.md
+++ b/doc/api/sidekiq_metrics.md
@@ -1,4 +1,4 @@
-# Sidekiq Metrics
+# Sidekiq Metrics API
>**Note:** This endpoint is only available on GitLab 8.9 and above.
@@ -15,7 +15,7 @@ GET /sidekiq/queue_metrics
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/sidekiq/queue_metrics
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/sidekiq/queue_metrics
```
Example response:
@@ -40,7 +40,7 @@ GET /sidekiq/process_metrics
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/sidekiq/process_metrics
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/sidekiq/process_metrics
```
Example response:
@@ -82,7 +82,7 @@ GET /sidekiq/job_stats
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/sidekiq/job_stats
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/sidekiq/job_stats
```
Example response:
@@ -106,7 +106,7 @@ GET /sidekiq/compound_metrics
```
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/sidekiq/compound_metrics
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/sidekiq/compound_metrics
```
Example response:
diff --git a/doc/api/snippets.md b/doc/api/snippets.md
new file mode 100644
index 00000000000..efaab712367
--- /dev/null
+++ b/doc/api/snippets.md
@@ -0,0 +1,236 @@
+# Snippets API
+
+> [Introduced][ce-6373] in GitLab 8.15.
+
+### Snippet visibility level
+
+Snippets in GitLab can be either private, internal, or public.
+You can set it with the `visibility` field in the snippet.
+
+Constants for snippet visibility levels are:
+
+| Visibility | Description |
+| ---------- | ----------- |
+| `private` | The snippet is visible only to the snippet creator |
+| `internal` | The snippet is visible for any logged in user |
+| `public` | The snippet can be accessed without any authentication |
+
+## List snippets
+
+Get a list of current user's snippets.
+
+```
+GET /snippets
+```
+
+## Single snippet
+
+Get a single snippet.
+
+```
+GET /snippets/:id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | Integer | yes | The ID of a snippet |
+
+``` bash
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/snippets/1
+```
+
+Example response:
+
+``` json
+{
+ "id": 1,
+ "title": "test",
+ "file_name": "add.rb",
+ "description": "Ruby test snippet",
+ "author": {
+ "id": 1,
+ "username": "john_smith",
+ "email": "john@example.com",
+ "name": "John Smith",
+ "state": "active",
+ "created_at": "2012-05-23T08:00:58Z"
+ },
+ "expires_at": null,
+ "updated_at": "2012-06-28T10:52:04Z",
+ "created_at": "2012-06-28T10:52:04Z",
+ "web_url": "http://example.com/snippets/1",
+}
+```
+
+## Create new snippet
+
+Creates a new snippet. The user must have permission to create new snippets.
+
+```
+POST /snippets
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `title` | String | yes | The title of a snippet |
+| `file_name` | String | yes | The name of a snippet file |
+| `content` | String | yes | The content of a snippet |
+| `description` | String | no | The description of a snippet |
+| `visibility` | String | no | The snippet's visibility |
+
+
+``` bash
+curl --request POST --data '{"title": "This is a snippet", "content": "Hello world", "description": "Hello World snippet", "file_name": "test.txt", "visibility": "internal" }' --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/snippets
+```
+
+Example response:
+
+``` json
+{
+ "id": 1,
+ "title": "This is a snippet",
+ "file_name": "test.txt",
+ "description": "Hello World snippet",
+ "author": {
+ "id": 1,
+ "username": "john_smith",
+ "email": "john@example.com",
+ "name": "John Smith",
+ "state": "active",
+ "created_at": "2012-05-23T08:00:58Z"
+ },
+ "expires_at": null,
+ "updated_at": "2012-06-28T10:52:04Z",
+ "created_at": "2012-06-28T10:52:04Z",
+ "web_url": "http://example.com/snippets/1",
+}
+```
+
+## Update snippet
+
+Updates an existing snippet. The user must have permission to change an existing snippet.
+
+```
+PUT /snippets/:id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | Integer | yes | The ID of a snippet |
+| `title` | String | no | The title of a snippet |
+| `file_name` | String | no | The name of a snippet file |
+| `description` | String | no | The description of a snippet |
+| `content` | String | no | The content of a snippet |
+| `visibility` | String | no | The snippet's visibility |
+
+
+``` bash
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data '{"title": "foo", "content": "bar"}' https://gitlab.example.com/api/v4/snippets/1
+```
+
+Example response:
+
+``` json
+{
+ "id": 1,
+ "title": "test",
+ "file_name": "add.rb",
+ "description": "description of snippet",
+ "author": {
+ "id": 1,
+ "username": "john_smith",
+ "email": "john@example.com",
+ "name": "John Smith",
+ "state": "active",
+ "created_at": "2012-05-23T08:00:58Z"
+ },
+ "expires_at": null,
+ "updated_at": "2012-06-28T10:52:04Z",
+ "created_at": "2012-06-28T10:52:04Z",
+ "web_url": "http://example.com/snippets/1",
+}
+```
+
+## Delete snippet
+
+Deletes an existing snippet.
+
+```
+DELETE /snippets/:id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | Integer | yes | The ID of a snippet |
+
+
+```
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/snippets/1"
+```
+
+upon successful delete a `204 No content` HTTP code shall be expected, with no data,
+but if the snippet is non-existent, a `404 Not Found` will be returned.
+
+## Explore all public snippets
+
+```
+GET /snippets/public
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `per_page` | Integer | no | number of snippets to return per page |
+| `page` | Integer | no | the page to retrieve |
+
+``` bash
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/snippets/public?per_page=2&page=1
+```
+
+Example response:
+
+``` json
+[
+ {
+ "author": {
+ "avatar_url": "http://www.gravatar.com/avatar/edaf55a9e363ea263e3b981d09e0f7f7?s=80&d=identicon",
+ "id": 12,
+ "name": "Libby Rolfson",
+ "state": "active",
+ "username": "elton_wehner",
+ "web_url": "http://localhost:3000/elton_wehner"
+ },
+ "created_at": "2016-11-25T16:53:34.504Z",
+ "file_name": "oconnerrice.rb",
+ "id": 49,
+ "raw_url": "http://localhost:3000/snippets/49/raw",
+ "title": "Ratione cupiditate et laborum temporibus.",
+ "updated_at": "2016-11-25T16:53:34.504Z",
+ "web_url": "http://localhost:3000/snippets/49"
+ },
+ {
+ "author": {
+ "avatar_url": "http://www.gravatar.com/avatar/36583b28626de71061e6e5a77972c3bd?s=80&d=identicon",
+ "id": 16,
+ "name": "Llewellyn Flatley",
+ "state": "active",
+ "username": "adaline",
+ "web_url": "http://localhost:3000/adaline"
+ },
+ "created_at": "2016-11-25T16:53:34.479Z",
+ "file_name": "muellershields.rb",
+ "id": 48,
+ "raw_url": "http://localhost:3000/snippets/48/raw",
+ "title": "Minus similique nesciunt vel fugiat qui ullam sunt.",
+ "updated_at": "2016-11-25T16:53:34.479Z",
+ "web_url": "http://localhost:3000/snippets/48"
+ }
+]
+```
diff --git a/doc/api/system_hooks.md b/doc/api/system_hooks.md
index 1802fae14fe..9750475f0a6 100644
--- a/doc/api/system_hooks.md
+++ b/doc/api/system_hooks.md
@@ -1,4 +1,4 @@
-# System hooks
+# System hooks API
All methods require administrator authorization.
@@ -20,18 +20,21 @@ GET /hooks
Example request:
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/hooks
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/hooks
```
Example response:
```json
[
- {
- "id" : 1,
- "url" : "https://gitlab.example.com/hook",
- "created_at" : "2015-11-04T20:07:35.874Z"
- }
+ {
+ "id":1,
+ "url":"https://gitlab.example.com/hook",
+ "created_at":"2016-10-31T12:32:15.192Z",
+ "push_events":true,
+ "tag_push_events":false,
+ "enable_ssl_verification":true
+ }
]
```
@@ -48,22 +51,29 @@ POST /hooks
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `url` | string | yes | The hook URL |
+| `token` | string | no | Secret token to validate received payloads; this will not be returned in the response |
+| `push_events` | boolean | no | When true, the hook will fire on push events |
+| `tag_push_events` | boolean | no | When true, the hook will fire on new tags being pushed |
+| `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook |
Example request:
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/hooks?url=https://gitlab.example.com/hook"
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/hooks?url=https://gitlab.example.com/hook"
```
Example response:
```json
[
- {
- "id" : 2,
- "url" : "https://gitlab.example.com/hook",
- "created_at" : "2015-11-04T20:07:35.874Z"
- }
+ {
+ "id":1,
+ "url":"https://gitlab.example.com/hook",
+ "created_at":"2016-10-31T12:32:15.192Z",
+ "push_events":true,
+ "tag_push_events":false,
+ "enable_ssl_verification":true
+ }
]
```
@@ -80,7 +90,7 @@ GET /hooks/:id
Example request:
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/hooks/2
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/hooks/2
```
Example response:
@@ -98,11 +108,7 @@ Example response:
## Delete system hook
-Deletes a system hook. This is an idempotent API function and returns `200 OK`
-even if the hook is not available.
-
-If the hook is deleted, a JSON object is returned. An error is raised if the
-hook is not found.
+Deletes a system hook.
---
@@ -117,24 +123,5 @@ DELETE /hooks/:id
Example request:
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/hooks/2
-```
-
-Example response:
-
-```json
-{
- "note_events" : false,
- "project_id" : null,
- "enable_ssl_verification" : true,
- "url" : "https://gitlab.example.com/hook",
- "updated_at" : "2015-11-04T20:12:15.931Z",
- "issues_events" : false,
- "merge_requests_events" : false,
- "created_at" : "2015-11-04T20:12:15.931Z",
- "service_id" : null,
- "id" : 2,
- "push_events" : true,
- "tag_push_events" : false
-}
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/hooks/2
```
diff --git a/doc/api/tags.md b/doc/api/tags.md
index 54059117456..54f092d1d30 100644
--- a/doc/api/tags.md
+++ b/doc/api/tags.md
@@ -1,8 +1,10 @@
-# Tags
+# Tags API
## List project repository tags
-Get a list of repository tags from a project, sorted by name in reverse alphabetical order.
+Get a list of repository tags from a project, sorted by name in reverse
+alphabetical order. This endpoint can be accessed without authentication if the
+repository is publicly accessible.
```
GET /projects/:id/repository/tags
@@ -10,7 +12,7 @@ GET /projects/:id/repository/tags
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
```json
[
@@ -24,7 +26,7 @@ Parameters:
"committer_email": "jack@example.com",
"id": "2695effb5807a22ff3d138d593fd856244e155e7",
"message": "Initial commit",
- "parents_ids": [
+ "parent_ids": [
"2a4b78934375d7f53875269ffd4f45fd83a84ebe"
]
},
@@ -40,9 +42,8 @@ Parameters:
## Get a single repository tag
-Get a specific repository tag determined by its name. It returns `200` together
-with the tag information if the tag exists. It returns `404` if the tag does not
-exist.
+Get a specific repository tag determined by its name. This endpoint can be
+accessed without authentication if the repository is publicly accessible.
```
GET /projects/:id/repository/tags/:tag_name
@@ -52,11 +53,11 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `tag_name` | string | yes | The name of the tag |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/repository/tags/v1.0.0
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/repository/tags/v1.0.0
```
Example Response:
@@ -92,7 +93,7 @@ POST /projects/:id/repository/tags
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `tag_name` (required) - The name of a tag
- `ref` (required) - Create tag using commit SHA, another tag name, or branch name.
- `message` (optional) - Creates annotated tag.
@@ -109,7 +110,7 @@ Parameters:
"committer_email": "jack@example.com",
"id": "2695effb5807a22ff3d138d593fd856244e155e7",
"message": "Initial commit",
- "parents_ids": [
+ "parent_ids": [
"2a4b78934375d7f53875269ffd4f45fd83a84ebe"
]
},
@@ -124,14 +125,12 @@ Parameters:
The message will be `nil` when creating a lightweight tag otherwise
it will contain the annotation.
-It returns 200 if the operation succeed. In case of an error,
-405 with an explaining error message is returned.
+In case of an error,
+status code `405` with an explaining error message is returned.
## Delete a tag
-Deletes a tag of a repository with given name. On success, this API method
-returns 200 with the name of the deleted tag. If the tag does not exist, the
-API returns 404.
+Deletes a tag of a repository with given name.
```
DELETE /projects/:id/repository/tags/:tag_name
@@ -139,20 +138,14 @@ DELETE /projects/:id/repository/tags/:tag_name
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `tag_name` (required) - The name of a tag
-```json
-{
- "tag_name": "v4.3.0"
-}
-```
## Create a new release
-Add release notes to the existing git tag. It returns 201 if the release is
-created successfully. If the tag does not exist, 404 is returned. If there
-already exists a release for the given tag, 409 is returned.
+Add release notes to the existing git tag. If there
+already exists a release for the given tag, status code `409` is returned.
```
POST /projects/:id/repository/tags/:tag_name/release
@@ -160,7 +153,7 @@ POST /projects/:id/repository/tags/:tag_name/release
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `tag_name` (required) - The name of a tag
- `description` (required) - Release notes with markdown support
@@ -173,9 +166,7 @@ Parameters:
## Update a release
-Updates the release notes of a given release. It returns 200 if the release is
-successfully updated. If the tag or the release does not exist, it returns 404
-with a proper error message.
+Updates the release notes of a given release.
```
PUT /projects/:id/repository/tags/:tag_name/release
@@ -183,7 +174,7 @@ PUT /projects/:id/repository/tags/:tag_name/release
Parameters:
-- `id` (required) - The ID of a project
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `tag_name` (required) - The name of a tag
- `description` (required) - Release notes with markdown support
diff --git a/doc/api/templates/gitignores.md b/doc/api/templates/gitignores.md
new file mode 100644
index 00000000000..d3f5c88ca90
--- /dev/null
+++ b/doc/api/templates/gitignores.md
@@ -0,0 +1,579 @@
+# Gitignores API
+
+## List gitignore templates
+
+Get all gitignore templates.
+
+```
+GET /templates/gitignores
+```
+
+```bash
+curl https://gitlab.example.com/api/v4/templates/gitignores
+```
+
+Example response:
+
+```json
+[
+ {
+ "name": "AppEngine"
+ },
+ {
+ "name": "Laravel"
+ },
+ {
+ "name": "Elisp"
+ },
+ {
+ "name": "SketchUp"
+ },
+ {
+ "name": "Ada"
+ },
+ {
+ "name": "Ruby"
+ },
+ {
+ "name": "Kohana"
+ },
+ {
+ "name": "Nanoc"
+ },
+ {
+ "name": "Erlang"
+ },
+ {
+ "name": "OCaml"
+ },
+ {
+ "name": "Lithium"
+ },
+ {
+ "name": "Fortran"
+ },
+ {
+ "name": "Scala"
+ },
+ {
+ "name": "Node"
+ },
+ {
+ "name": "Fancy"
+ },
+ {
+ "name": "Perl"
+ },
+ {
+ "name": "Zephir"
+ },
+ {
+ "name": "WordPress"
+ },
+ {
+ "name": "Symfony"
+ },
+ {
+ "name": "FuelPHP"
+ },
+ {
+ "name": "DM"
+ },
+ {
+ "name": "Sdcc"
+ },
+ {
+ "name": "Rust"
+ },
+ {
+ "name": "C"
+ },
+ {
+ "name": "Umbraco"
+ },
+ {
+ "name": "Actionscript"
+ },
+ {
+ "name": "Android"
+ },
+ {
+ "name": "Grails"
+ },
+ {
+ "name": "Composer"
+ },
+ {
+ "name": "ExpressionEngine"
+ },
+ {
+ "name": "Gcov"
+ },
+ {
+ "name": "Qt"
+ },
+ {
+ "name": "Phalcon"
+ },
+ {
+ "name": "ArchLinuxPackages"
+ },
+ {
+ "name": "TeX"
+ },
+ {
+ "name": "SCons"
+ },
+ {
+ "name": "Lilypond"
+ },
+ {
+ "name": "CommonLisp"
+ },
+ {
+ "name": "Rails"
+ },
+ {
+ "name": "Mercury"
+ },
+ {
+ "name": "Magento"
+ },
+ {
+ "name": "ChefCookbook"
+ },
+ {
+ "name": "GitBook"
+ },
+ {
+ "name": "C++"
+ },
+ {
+ "name": "Eagle"
+ },
+ {
+ "name": "Go"
+ },
+ {
+ "name": "OpenCart"
+ },
+ {
+ "name": "Scheme"
+ },
+ {
+ "name": "Typo3"
+ },
+ {
+ "name": "SeamGen"
+ },
+ {
+ "name": "Swift"
+ },
+ {
+ "name": "Elm"
+ },
+ {
+ "name": "Unity"
+ },
+ {
+ "name": "Agda"
+ },
+ {
+ "name": "CUDA"
+ },
+ {
+ "name": "VVVV"
+ },
+ {
+ "name": "Finale"
+ },
+ {
+ "name": "LemonStand"
+ },
+ {
+ "name": "Textpattern"
+ },
+ {
+ "name": "Julia"
+ },
+ {
+ "name": "Packer"
+ },
+ {
+ "name": "Scrivener"
+ },
+ {
+ "name": "Dart"
+ },
+ {
+ "name": "Plone"
+ },
+ {
+ "name": "Jekyll"
+ },
+ {
+ "name": "Xojo"
+ },
+ {
+ "name": "LabVIEW"
+ },
+ {
+ "name": "Autotools"
+ },
+ {
+ "name": "KiCad"
+ },
+ {
+ "name": "Prestashop"
+ },
+ {
+ "name": "ROS"
+ },
+ {
+ "name": "Smalltalk"
+ },
+ {
+ "name": "GWT"
+ },
+ {
+ "name": "OracleForms"
+ },
+ {
+ "name": "SugarCRM"
+ },
+ {
+ "name": "Nim"
+ },
+ {
+ "name": "SymphonyCMS"
+ },
+ {
+ "name": "Maven"
+ },
+ {
+ "name": "CFWheels"
+ },
+ {
+ "name": "Python"
+ },
+ {
+ "name": "ZendFramework"
+ },
+ {
+ "name": "CakePHP"
+ },
+ {
+ "name": "Concrete5"
+ },
+ {
+ "name": "PlayFramework"
+ },
+ {
+ "name": "Terraform"
+ },
+ {
+ "name": "Elixir"
+ },
+ {
+ "name": "CMake"
+ },
+ {
+ "name": "Joomla"
+ },
+ {
+ "name": "Coq"
+ },
+ {
+ "name": "Delphi"
+ },
+ {
+ "name": "Haskell"
+ },
+ {
+ "name": "Yii"
+ },
+ {
+ "name": "Java"
+ },
+ {
+ "name": "UnrealEngine"
+ },
+ {
+ "name": "AppceleratorTitanium"
+ },
+ {
+ "name": "CraftCMS"
+ },
+ {
+ "name": "ForceDotCom"
+ },
+ {
+ "name": "ExtJs"
+ },
+ {
+ "name": "MetaProgrammingSystem"
+ },
+ {
+ "name": "D"
+ },
+ {
+ "name": "Objective-C"
+ },
+ {
+ "name": "RhodesRhomobile"
+ },
+ {
+ "name": "R"
+ },
+ {
+ "name": "EPiServer"
+ },
+ {
+ "name": "Yeoman"
+ },
+ {
+ "name": "VisualStudio"
+ },
+ {
+ "name": "Processing"
+ },
+ {
+ "name": "Leiningen"
+ },
+ {
+ "name": "Stella"
+ },
+ {
+ "name": "Opa"
+ },
+ {
+ "name": "Drupal"
+ },
+ {
+ "name": "TurboGears2"
+ },
+ {
+ "name": "Idris"
+ },
+ {
+ "name": "Jboss"
+ },
+ {
+ "name": "CodeIgniter"
+ },
+ {
+ "name": "Qooxdoo"
+ },
+ {
+ "name": "Waf"
+ },
+ {
+ "name": "Sass"
+ },
+ {
+ "name": "Lua"
+ },
+ {
+ "name": "Clojure"
+ },
+ {
+ "name": "IGORPro"
+ },
+ {
+ "name": "Gradle"
+ },
+ {
+ "name": "Archives"
+ },
+ {
+ "name": "SynopsysVCS"
+ },
+ {
+ "name": "Ninja"
+ },
+ {
+ "name": "Tags"
+ },
+ {
+ "name": "OSX"
+ },
+ {
+ "name": "Dreamweaver"
+ },
+ {
+ "name": "CodeKit"
+ },
+ {
+ "name": "NotepadPP"
+ },
+ {
+ "name": "VisualStudioCode"
+ },
+ {
+ "name": "Mercurial"
+ },
+ {
+ "name": "BricxCC"
+ },
+ {
+ "name": "DartEditor"
+ },
+ {
+ "name": "Eclipse"
+ },
+ {
+ "name": "Cloud9"
+ },
+ {
+ "name": "TortoiseGit"
+ },
+ {
+ "name": "NetBeans"
+ },
+ {
+ "name": "GPG"
+ },
+ {
+ "name": "Espresso"
+ },
+ {
+ "name": "Redcar"
+ },
+ {
+ "name": "Xcode"
+ },
+ {
+ "name": "Matlab"
+ },
+ {
+ "name": "LyX"
+ },
+ {
+ "name": "SlickEdit"
+ },
+ {
+ "name": "Dropbox"
+ },
+ {
+ "name": "CVS"
+ },
+ {
+ "name": "Calabash"
+ },
+ {
+ "name": "JDeveloper"
+ },
+ {
+ "name": "Vagrant"
+ },
+ {
+ "name": "IPythonNotebook"
+ },
+ {
+ "name": "TextMate"
+ },
+ {
+ "name": "Ensime"
+ },
+ {
+ "name": "WebMethods"
+ },
+ {
+ "name": "VirtualEnv"
+ },
+ {
+ "name": "Emacs"
+ },
+ {
+ "name": "Momentics"
+ },
+ {
+ "name": "JetBrains"
+ },
+ {
+ "name": "SublimeText"
+ },
+ {
+ "name": "Kate"
+ },
+ {
+ "name": "ModelSim"
+ },
+ {
+ "name": "Redis"
+ },
+ {
+ "name": "KDevelop4"
+ },
+ {
+ "name": "Bazaar"
+ },
+ {
+ "name": "Linux"
+ },
+ {
+ "name": "Windows"
+ },
+ {
+ "name": "XilinxISE"
+ },
+ {
+ "name": "Lazarus"
+ },
+ {
+ "name": "EiffelStudio"
+ },
+ {
+ "name": "Anjuta"
+ },
+ {
+ "name": "Vim"
+ },
+ {
+ "name": "Otto"
+ },
+ {
+ "name": "MicrosoftOffice"
+ },
+ {
+ "name": "LibreOffice"
+ },
+ {
+ "name": "SBT"
+ },
+ {
+ "name": "MonoDevelop"
+ },
+ {
+ "name": "SVN"
+ },
+ {
+ "name": "FlexBuilder"
+ }
+]
+```
+
+## Single gitignore template
+
+Get a single gitignore template.
+
+```
+GET /templates/gitignores/:key
+```
+
+| Attribute | Type | Required | Description |
+| ---------- | ------ | -------- | ----------- |
+| `key` | string | yes | The key of the gitignore template |
+
+```bash
+curl https://gitlab.example.com/api/v4/templates/gitignores/Ruby
+```
+
+Example response:
+
+```json
+{
+ "name": "Ruby",
+ "content": "*.gem\n*.rbc\n/.config\n/coverage/\n/InstalledFiles\n/pkg/\n/spec/reports/\n/spec/examples.txt\n/test/tmp/\n/test/version_tmp/\n/tmp/\n\n# Used by dotenv library to load environment variables.\n# .env\n\n## Specific to RubyMotion:\n.dat*\n.repl_history\nbuild/\n*.bridgesupport\nbuild-iPhoneOS/\nbuild-iPhoneSimulator/\n\n## Specific to RubyMotion (use of CocoaPods):\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control\n#\n# vendor/Pods/\n\n## Documentation cache and generated files:\n/.yardoc/\n/_yardoc/\n/doc/\n/rdoc/\n\n## Environment normalization:\n/.bundle/\n/vendor/bundle\n/lib/bundler/man/\n\n# for a library or gem, you might want to ignore these files since the code is\n# intended to run in multiple environments; otherwise, check them in:\n# Gemfile.lock\n# .ruby-version\n# .ruby-gemset\n\n# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:\n.rvmrc\n"
+}
+```
diff --git a/doc/api/templates/gitlab_ci_ymls.md b/doc/api/templates/gitlab_ci_ymls.md
new file mode 100644
index 00000000000..bdb128fc336
--- /dev/null
+++ b/doc/api/templates/gitlab_ci_ymls.md
@@ -0,0 +1,120 @@
+# GitLab CI YMLs API
+
+## List GitLab CI YML templates
+
+Get all GitLab CI YML templates.
+
+```
+GET /templates/gitlab_ci_ymls
+```
+
+```bash
+curl https://gitlab.example.com/api/v4/templates/gitlab_ci_ymls
+```
+
+Example response:
+
+```json
+[
+ {
+ "name": "C++"
+ },
+ {
+ "name": "Docker"
+ },
+ {
+ "name": "Elixir"
+ },
+ {
+ "name": "LaTeX"
+ },
+ {
+ "name": "Grails"
+ },
+ {
+ "name": "Rust"
+ },
+ {
+ "name": "Nodejs"
+ },
+ {
+ "name": "Ruby"
+ },
+ {
+ "name": "Scala"
+ },
+ {
+ "name": "Maven"
+ },
+ {
+ "name": "Harp"
+ },
+ {
+ "name": "Pelican"
+ },
+ {
+ "name": "Hyde"
+ },
+ {
+ "name": "Nanoc"
+ },
+ {
+ "name": "Octopress"
+ },
+ {
+ "name": "JBake"
+ },
+ {
+ "name": "HTML"
+ },
+ {
+ "name": "Hugo"
+ },
+ {
+ "name": "Metalsmith"
+ },
+ {
+ "name": "Hexo"
+ },
+ {
+ "name": "Lektor"
+ },
+ {
+ "name": "Doxygen"
+ },
+ {
+ "name": "Brunch"
+ },
+ {
+ "name": "Jekyll"
+ },
+ {
+ "name": "Middleman"
+ }
+]
+```
+
+## Single GitLab CI YML template
+
+Get a single GitLab CI YML template.
+
+```
+GET /templates/gitlab_ci_ymls/:key
+```
+
+| Attribute | Type | Required | Description |
+| ---------- | ------ | -------- | ----------- |
+| `key` | string | yes | The key of the GitLab CI YML template |
+
+```bash
+curl https://gitlab.example.com/api/v4/templates/gitlab_ci_ymls/Ruby
+```
+
+Example response:
+
+```json
+{
+ "name": "Ruby",
+ "content": "# This file is a template, and might need editing before it works on your project.\n# Official language image. Look for the different tagged releases at:\n# https://hub.docker.com/r/library/ruby/tags/\nimage: \"ruby:2.3\"\n\n# Pick zero or more services to be used on all builds.\n# Only needed when using a docker container to run your tests in.\n# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-service\nservices:\n - mysql:latest\n - redis:latest\n - postgres:latest\n\nvariables:\n POSTGRES_DB: database_name\n\n# Cache gems in between builds\ncache:\n paths:\n - vendor/ruby\n\n# This is a basic example for a gem or script which doesn't use\n# services such as redis or postgres\nbefore_script:\n - ruby -v # Print out ruby version for debugging\n # Uncomment next line if your rails app needs a JS runtime:\n # - apt-get update -q && apt-get install nodejs -yqq\n - gem install bundler --no-ri --no-rdoc # Bundler is not installed with the image\n - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby\n\n# Optional - Delete if not using `rubocop`\nrubocop:\n script:\n - rubocop\n\nrspec:\n script:\n - rspec spec\n\nrails:\n variables:\n DATABASE_URL: \"postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB\"\n script:\n - bundle exec rake db:migrate\n - bundle exec rake db:seed\n - bundle exec rake test\n"
+}
+```
diff --git a/doc/api/licenses.md b/doc/api/templates/licenses.md
index ed26d1fb7fb..8d1006e08c5 100644
--- a/doc/api/licenses.md
+++ b/doc/api/templates/licenses.md
@@ -1,11 +1,11 @@
-# Licenses
+# Licenses API
## List license templates
Get all license templates.
```
-GET /licenses
+GET /templates/licenses
```
| Attribute | Type | Required | Description |
@@ -13,7 +13,7 @@ GET /licenses
| `popular` | boolean | no | If passed, returns only popular licenses |
```bash
-curl https://gitlab.example.com/api/v3/licenses?popular=1
+curl https://gitlab.example.com/api/v4/templates/licenses?popular=1
```
Example response:
@@ -102,7 +102,7 @@ Get a single license template. You can pass parameters to replace the license
placeholder.
```
-GET /licenses/:key
+GET /templates/licenses/:key
```
| Attribute | Type | Required | Description |
@@ -116,7 +116,7 @@ If you omit the `fullname` parameter but authenticate your request, the name of
the authenticated user will be used to replace the copyright holder placeholder.
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/licenses/mit?project=My+Cool+Project
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/templates/licenses/mit?project=My+Cool+Project
```
Example response:
diff --git a/doc/api/todos.md b/doc/api/todos.md
index 0cd644dfd2f..dd4c737b729 100644
--- a/doc/api/todos.md
+++ b/doc/api/todos.md
@@ -1,4 +1,4 @@
-# Todos
+# Todos API
> [Introduced][ce-3188] in GitLab 8.10.
@@ -22,7 +22,7 @@ Parameters:
| `type` | string | no | The type of a todo. Can be either `Issue` or `MergeRequest` |
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/todos
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/todos
```
Example Response:
@@ -44,7 +44,7 @@ Example Response:
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/root"
+ "web_url": "https://gitlab.example.com/root"
},
"action_name": "marked",
"target_type": "MergeRequest",
@@ -67,7 +67,7 @@ Example Response:
"id": 12,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/craig_rutherford"
+ "web_url": "https://gitlab.example.com/craig_rutherford"
},
"assignee": {
"name": "Administrator",
@@ -75,7 +75,7 @@ Example Response:
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/root"
+ "web_url": "https://gitlab.example.com/root"
},
"source_project_id": 2,
"target_project_id": 2,
@@ -92,7 +92,7 @@ Example Response:
"updated_at": "2016-06-17T07:47:34.163Z",
"due_date": null
},
- "merge_when_build_succeeds": false,
+ "merge_when_pipeline_succeeds": false,
"merge_status": "cannot_be_merged",
"subscribed": true,
"user_notes_count": 7
@@ -117,7 +117,7 @@ Example Response:
"id": 12,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/craig_rutherford"
+ "web_url": "https://gitlab.example.com/craig_rutherford"
},
"action_name": "assigned",
"target_type": "MergeRequest",
@@ -140,7 +140,7 @@ Example Response:
"id": 12,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/craig_rutherford"
+ "web_url": "https://gitlab.example.com/craig_rutherford"
},
"assignee": {
"name": "Administrator",
@@ -148,7 +148,7 @@ Example Response:
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/root"
+ "web_url": "https://gitlab.example.com/root"
},
"source_project_id": 2,
"target_project_id": 2,
@@ -165,7 +165,7 @@ Example Response:
"updated_at": "2016-06-17T07:47:34.163Z",
"due_date": null
},
- "merge_when_build_succeeds": false,
+ "merge_when_pipeline_succeeds": false,
"merge_status": "cannot_be_merged",
"subscribed": true,
"user_notes_count": 7
@@ -184,7 +184,7 @@ Marks a single pending todo given by its ID for the current user as done. The
todo marked as done is returned in the response.
```
-DELETE /todos/:id
+POST /todos/:id/mark_as_done
```
Parameters:
@@ -194,7 +194,7 @@ Parameters:
| `id` | integer | yes | The ID of a todo |
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/todos/130
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/todos/130/mark_as_done
```
Example Response:
@@ -215,7 +215,7 @@ Example Response:
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/root"
+ "web_url": "https://gitlab.example.com/root"
},
"action_name": "marked",
"target_type": "MergeRequest",
@@ -238,7 +238,7 @@ Example Response:
"id": 12,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/craig_rutherford"
+ "web_url": "https://gitlab.example.com/craig_rutherford"
},
"assignee": {
"name": "Administrator",
@@ -246,7 +246,7 @@ Example Response:
"id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/u/root"
+ "web_url": "https://gitlab.example.com/root"
},
"source_project_id": 2,
"target_project_id": 2,
@@ -263,7 +263,7 @@ Example Response:
"updated_at": "2016-06-17T07:47:34.163Z",
"due_date": null
},
- "merge_when_build_succeeds": false,
+ "merge_when_pipeline_succeeds": false,
"merge_status": "cannot_be_merged",
"subscribed": true,
"user_notes_count": 7
@@ -277,20 +277,15 @@ Example Response:
## Mark all todos as done
-Marks all pending todos for the current user as done. It returns the number of marked todos.
+Marks all pending todos for the current user as done. It returns the HTTP status code `204` with an empty response.
```
-DELETE /todos
+POST /todos/mark_as_done
```
```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/todos
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/todos/donmark_as_donee
```
-Example Response:
-
-```json
-3
-```
[ce-3188]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3188
diff --git a/doc/api/users.md b/doc/api/users.md
index 9be4f2e6ec3..cf09b8f44aa 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -1,4 +1,4 @@
-# Users
+# Users API
## List users
@@ -20,7 +20,7 @@ GET /users
"name": "John Smith",
"state": "active",
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg",
- "web_url": "http://localhost:3000/u/john_smith"
+ "web_url": "http://localhost:3000/john_smith"
},
{
"id": 2,
@@ -28,11 +28,23 @@ GET /users
"name": "Jack Smith",
"state": "blocked",
"avatar_url": "http://gravatar.com/../e32131cd8.jpeg",
- "web_url": "http://localhost:3000/u/jack_smith"
+ "web_url": "http://localhost:3000/jack_smith"
}
]
```
+In addition, you can filter users based on states eg. `blocked`, `active`
+This works only to filter users who are `blocked` or `active`.
+It does not support `active=false` or `blocked=false`.
+
+```
+GET /users?active=true
+```
+
+```
+GET /users?blocked=true
+```
+
### For admins
```
@@ -48,7 +60,7 @@ GET /users
"name": "John Smith",
"state": "active",
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg",
- "web_url": "http://localhost:3000/u/john_smith",
+ "web_url": "http://localhost:3000/john_smith",
"created_at": "2012-05-23T08:00:58Z",
"is_admin": false,
"bio": null,
@@ -60,7 +72,7 @@ GET /users
"organization": "",
"last_sign_in_at": "2012-06-01T11:41:01Z",
"confirmed_at": "2012-05-23T09:05:22Z",
- "theme_id": 1,
+ "last_activity_on": "2012-05-23",
"color_scheme_id": 2,
"projects_limit": 100,
"current_sign_in_at": "2012-06-02T06:36:55Z",
@@ -81,7 +93,7 @@ GET /users
"name": "Jack Smith",
"state": "blocked",
"avatar_url": "http://localhost:3000/uploads/user/avatar/2/index.jpg",
- "web_url": "http://localhost:3000/u/jack_smith",
+ "web_url": "http://localhost:3000/jack_smith",
"created_at": "2012-05-23T08:01:01Z",
"is_admin": false,
"bio": null,
@@ -93,7 +105,7 @@ GET /users
"organization": "",
"last_sign_in_at": null,
"confirmed_at": "2012-05-30T16:53:06.148Z",
- "theme_id": 1,
+ "last_activity_on": "2012-05-23",
"color_scheme_id": 3,
"projects_limit": 100,
"current_sign_in_at": "2014-03-19T17:54:13Z",
@@ -120,6 +132,20 @@ For example:
GET /users?username=jack_smith
```
+You can also lookup users by external UID and provider:
+
+```
+GET /users?extern_uid=:extern_uid&provider=:provider
+```
+
+For example:
+
+```
+GET /users?extern_uid=1234567&provider=github
+```
+
+You can search for users who are external with: `/users?external=true`
+
## Single user
Get a single user.
@@ -141,9 +167,8 @@ Parameters:
"name": "John Smith",
"state": "active",
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg",
- "web_url": "http://localhost:3000/u/john_smith",
+ "web_url": "http://localhost:3000/john_smith",
"created_at": "2012-05-23T08:00:58Z",
- "is_admin": false,
"bio": null,
"location": null,
"skype": "",
@@ -172,7 +197,7 @@ Parameters:
"name": "John Smith",
"state": "active",
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg",
- "web_url": "http://localhost:3000/u/john_smith",
+ "web_url": "http://localhost:3000/john_smith",
"created_at": "2012-05-23T08:00:58Z",
"is_admin": false,
"bio": null,
@@ -184,7 +209,7 @@ Parameters:
"organization": "",
"last_sign_in_at": "2012-06-01T11:41:01Z",
"confirmed_at": "2012-05-23T09:05:22Z",
- "theme_id": 1,
+ "last_activity_on": "2012-05-23",
"color_scheme_id": 2,
"projects_limit": 100,
"current_sign_in_at": "2012-06-02T06:36:55Z",
@@ -202,7 +227,7 @@ Parameters:
## User creation
-Creates a new user. Note only administrators can create new users.
+Creates a new user. Note only administrators can create new users. Either `password` or `reset_password` should be specified (`reset_password` takes priority).
```
POST /users
@@ -211,7 +236,8 @@ POST /users
Parameters:
- `email` (required) - Email
-- `password` (required) - Password
+- `password` (optional) - Password
+- `reset_password` (optional) - Send user password reset link - true or false(default)
- `username` (required) - Username
- `name` (required) - Name
- `skype` (optional) - Skype ID
@@ -228,6 +254,7 @@ Parameters:
- `can_create_group` (optional) - User can create groups - true or false
- `confirm` (optional) - Require confirmation - true (default) or false
- `external` (optional) - Flags the user as external - true or false(default)
+- `avatar` (optional) - Image file for user's avatar
## User modification
@@ -256,9 +283,11 @@ Parameters:
- `admin` (optional) - User is admin - true or false (default)
- `can_create_group` (optional) - User can create groups - true or false
- `external` (optional) - Flags the user as external - true or false(default)
+- `avatar` (optional) - Image file for user's avatar
-Note, at the moment this method does only return a 404 error,
-even in cases where a 409 (Conflict) would be more appropriate,
+On password update, user will be forced to change it upon next login.
+Note, at the moment this method does only return a `404` error,
+even in cases where a `409` (Conflict) would be more appropriate,
e.g. when renaming the email address to some existing one.
## User deletion
@@ -276,8 +305,13 @@ DELETE /users/:id
Parameters:
- `id` (required) - The ID of the user
+- `hard_delete` (optional) - If true, contributions that would usually be
+ [moved to the ghost user](../user/profile/account/delete_account.md#associated-records)
+ will be deleted instead, as well as groups owned solely by this user.
-## Current user
+## User
+
+### For normal users
Gets currently authenticated user.
@@ -293,9 +327,8 @@ GET /user
"name": "John Smith",
"state": "active",
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg",
- "web_url": "http://localhost:3000/u/john_smith",
+ "web_url": "http://localhost:3000/john_smith",
"created_at": "2012-05-23T08:00:58Z",
- "is_admin": false,
"bio": null,
"location": null,
"skype": "",
@@ -305,7 +338,7 @@ GET /user
"organization": "",
"last_sign_in_at": "2012-06-01T11:41:01Z",
"confirmed_at": "2012-05-23T09:05:22Z",
- "theme_id": 1,
+ "last_activity_on": "2012-05-23",
"color_scheme_id": 2,
"projects_limit": 100,
"current_sign_in_at": "2012-06-02T06:36:55Z",
@@ -321,6 +354,53 @@ GET /user
}
```
+### For admins
+
+Parameters:
+
+- `sudo` (required) - the ID of a user
+
+```
+GET /user
+```
+
+```json
+{
+ "id": 1,
+ "username": "john_smith",
+ "email": "john@example.com",
+ "name": "John Smith",
+ "state": "active",
+ "avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg",
+ "web_url": "http://localhost:3000/john_smith",
+ "created_at": "2012-05-23T08:00:58Z",
+ "is_admin": false,
+ "bio": null,
+ "location": null,
+ "skype": "",
+ "linkedin": "",
+ "twitter": "",
+ "website_url": "",
+ "organization": "",
+ "last_sign_in_at": "2012-06-01T11:41:01Z",
+ "confirmed_at": "2012-05-23T09:05:22Z",
+ "last_activity_on": "2012-05-23",
+ "color_scheme_id": 2,
+ "projects_limit": 100,
+ "current_sign_in_at": "2012-06-02T06:36:55Z",
+ "identities": [
+ {"provider": "github", "extern_uid": "2435223452345"},
+ {"provider": "bitbucket", "extern_uid": "john_smith"},
+ {"provider": "google_oauth2", "extern_uid": "8776128412476123468721346"}
+ ],
+ "can_create_group": true,
+ "can_create_project": true,
+ "two_factor_enabled": true,
+ "external": false,
+ "private_token": "dd34asd13as"
+}
+```
+
## List SSH keys
Get a list of currently authenticated user's SSH keys.
@@ -355,24 +435,24 @@ Parameters:
Get a list of a specified user's SSH keys. Available only for admin
```
-GET /users/:uid/keys
+GET /users/:id/keys
```
Parameters:
-- `uid` (required) - id of specified user
+- `id` (required) - id of specified user
## Single SSH key
Get a single key.
```
-GET /user/keys/:id
+GET /user/keys/:key_id
```
Parameters:
-- `id` (required) - The ID of an SSH key
+- `key_id` (required) - The ID of an SSH key
```json
{
@@ -435,8 +515,6 @@ Parameters:
- `title` (required) - new SSH Key's title
- `key` (required) - new SSH key
-Will return created key with status `201 Created` on success, or `404 Not found` on fail.
-
## Delete SSH key for current user
Deletes key owned by currently authenticated user.
@@ -444,25 +522,25 @@ This is an idempotent function and calling it on a key that is already deleted
or not available results in `200 OK`.
```
-DELETE /user/keys/:id
+DELETE /user/keys/:key_id
```
Parameters:
-- `id` (required) - SSH key ID
+- `key_id` (required) - SSH key ID
## Delete SSH key for given user
Deletes key owned by a specified user. Available only for admin.
```
-DELETE /users/:uid/keys/:id
+DELETE /users/:id/keys/:key_id
```
Parameters:
-- `uid` (required) - id of specified user
-- `id` (required) - SSH key ID
+- `id` (required) - id of specified user
+- `key_id` (required) - SSH key ID
Will return `200 OK` on success, or `404 Not found` if either user or key cannot be found.
@@ -496,24 +574,24 @@ Parameters:
Get a list of a specified user's emails. Available only for admin
```
-GET /users/:uid/emails
+GET /users/:id/emails
```
Parameters:
-- `uid` (required) - id of specified user
+- `id` (required) - id of specified user
## Single email
Get a single email.
```
-GET /user/emails/:id
+GET /user/emails/:email_id
```
Parameters:
-- `id` (required) - email ID
+- `email_id` (required) - email ID
```json
{
@@ -567,8 +645,6 @@ Parameters:
- `id` (required) - id of specified user
- `email` (required) - email address
-Will return created email with status `201 Created` on success, or `404 Not found` on fail.
-
## Delete email for current user
Deletes email owned by currently authenticated user.
@@ -576,25 +652,25 @@ This is an idempotent function and calling it on a email that is already deleted
or not available results in `200 OK`.
```
-DELETE /user/emails/:id
+DELETE /user/emails/:email_id
```
Parameters:
-- `id` (required) - email ID
+- `email_id` (required) - email ID
## Delete email for given user
Deletes email owned by a specified user. Available only for admin.
```
-DELETE /users/:uid/emails/:id
+DELETE /users/:id/emails/:email_id
```
Parameters:
-- `uid` (required) - id of specified user
-- `id` (required) - email ID
+- `id` (required) - id of specified user
+- `email_id` (required) - email ID
Will return `200 OK` on success, or `404 Not found` if either user or email cannot be found.
@@ -603,14 +679,14 @@ Will return `200 OK` on success, or `404 Not found` if either user or email cann
Blocks the specified user. Available only for admin.
```
-PUT /users/:uid/block
+POST /users/:id/block
```
Parameters:
-- `uid` (required) - id of specified user
+- `id` (required) - id of specified user
-Will return `200 OK` on success, `404 User Not Found` is user cannot be found or
+Will return `201 OK` on success, `404 User Not Found` is user cannot be found or
`403 Forbidden` when trying to block an already blocked user by LDAP synchronization.
## Unblock user
@@ -618,12 +694,228 @@ Will return `200 OK` on success, `404 User Not Found` is user cannot be found or
Unblocks the specified user. Available only for admin.
```
-PUT /users/:uid/unblock
+POST /users/:id/unblock
```
Parameters:
-- `uid` (required) - id of specified user
+- `id` (required) - id of specified user
-Will return `200 OK` on success, `404 User Not Found` is user cannot be found or
+Will return `201 OK` on success, `404 User Not Found` is user cannot be found or
`403 Forbidden` when trying to unblock a user blocked by LDAP synchronization.
+
+### Get user contribution events
+
+Please refer to the [Events API documentation](events.md#get-user-contribution-events)
+
+
+## Get all impersonation tokens of a user
+
+> Requires admin permissions.
+
+It retrieves every impersonation token of the user. Use the pagination
+parameters `page` and `per_page` to restrict the list of impersonation tokens.
+
+```
+GET /users/:user_id/impersonation_tokens
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `user_id` | integer | yes | The ID of the user |
+| `state` | string | no | filter tokens based on state (`all`, `active`, `inactive`) |
+
+```
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/42/impersonation_tokens
+```
+
+Example response:
+
+```json
+[
+ {
+ "active" : true,
+ "token" : "EsMo-vhKfXGwX9RKrwiy",
+ "scopes" : [
+ "api"
+ ],
+ "revoked" : false,
+ "name" : "mytoken",
+ "id" : 2,
+ "created_at" : "2017-03-17T17:18:09.283Z",
+ "impersonation" : true,
+ "expires_at" : "2017-04-04"
+ },
+ {
+ "active" : false,
+ "scopes" : [
+ "read_user"
+ ],
+ "revoked" : true,
+ "token" : "ZcZRpLeEuQRprkRjYydY",
+ "name" : "mytoken2",
+ "created_at" : "2017-03-17T17:19:28.697Z",
+ "id" : 3,
+ "impersonation" : true,
+ "expires_at" : "2017-04-14"
+ }
+]
+```
+
+## Get an impersonation token of a user
+
+> Requires admin permissions.
+
+It shows a user's impersonation token.
+
+```
+GET /users/:user_id/impersonation_tokens/:impersonation_token_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `user_id` | integer | yes | The ID of the user |
+| `impersonation_token_id` | integer | yes | The ID of the impersonation token |
+
+```
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/42/impersonation_tokens/2
+```
+
+Example response:
+
+```json
+{
+ "active" : true,
+ "token" : "EsMo-vhKfXGwX9RKrwiy",
+ "scopes" : [
+ "api"
+ ],
+ "revoked" : false,
+ "name" : "mytoken",
+ "id" : 2,
+ "created_at" : "2017-03-17T17:18:09.283Z",
+ "impersonation" : true,
+ "expires_at" : "2017-04-04"
+}
+```
+
+## Create an impersonation token
+
+> Requires admin permissions.
+
+It creates a new impersonation token. Note that only administrators can do this.
+You are only able to create impersonation tokens to impersonate the user and perform
+both API calls and Git reads and writes. The user will not see these tokens in their profile
+settings page.
+
+```
+POST /users/:user_id/impersonation_tokens
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `user_id` | integer | yes | The ID of the user |
+| `name` | string | yes | The name of the impersonation token |
+| `expires_at` | date | no | The expiration date of the impersonation token in ISO format (`YYYY-MM-DD`)|
+| `scopes` | array | yes | The array of scopes of the impersonation token (`api`, `read_user`) |
+
+```
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "name=mytoken" --data "expires_at=2017-04-04" --data "scopes[]=api" https://gitlab.example.com/api/v4/users/42/impersonation_tokens
+```
+
+Example response:
+
+```json
+{
+ "id" : 2,
+ "revoked" : false,
+ "scopes" : [
+ "api"
+ ],
+ "token" : "EsMo-vhKfXGwX9RKrwiy",
+ "active" : true,
+ "impersonation" : true,
+ "name" : "mytoken",
+ "created_at" : "2017-03-17T17:18:09.283Z",
+ "expires_at" : "2017-04-04"
+}
+```
+
+## Revoke an impersonation token
+
+> Requires admin permissions.
+
+It revokes an impersonation token.
+
+```
+DELETE /users/:user_id/impersonation_tokens/:impersonation_token_id
+```
+
+```
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/users/42/impersonation_tokens/1
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `user_id` | integer | yes | The ID of the user |
+| `impersonation_token_id` | integer | yes | The ID of the impersonation token |
+
+### Get user activities (admin only)
+
+>**Note:** This API endpoint is only available on 8.15 (EE) and 9.1 (CE) and above.
+
+Get the last activity date for all users, sorted from oldest to newest.
+
+The activities that update the timestamp are:
+
+ - Git HTTP/SSH activities (such as clone, push)
+ - User logging in into GitLab
+
+By default, it shows the activity for all users in the last 6 months, but this can be
+amended by using the `from` parameter.
+
+```
+GET /user/activities
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `from` | string | no | Date string in the format YEAR-MONTH-DAY, e.g. `2016-03-11`. Defaults to 6 months ago. |
+
+```bash
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/user/activities
+```
+
+Example response:
+
+```json
+[
+ {
+ "username": "user1",
+ "last_activity_on": "2015-12-14",
+ "last_activity_at": "2015-12-14"
+ },
+ {
+ "username": "user2",
+ "last_activity_on": "2015-12-15",
+ "last_activity_at": "2015-12-15"
+ },
+ {
+ "username": "user3",
+ "last_activity_on": "2015-12-16",
+ "last_activity_at": "2015-12-16"
+ }
+]
+```
+
+Please note that `last_activity_at` is deprecated, please use `last_activity_on`.
diff --git a/doc/api/v3_to_v4.md b/doc/api/v3_to_v4.md
new file mode 100644
index 00000000000..9db8e0351cf
--- /dev/null
+++ b/doc/api/v3_to_v4.md
@@ -0,0 +1,85 @@
+# API V3 to API V4
+
+Since GitLab 9.0, API V4 is the preferred version to be used.
+
+API V3 will be removed in GitLab 9.5, to be released on August 22, 2017. In the
+meantime, we advise you to make any necessary changes to applications that use
+V3. The V3 API documentation is still [available](https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/doc/api/README.md).
+
+Below are the changes made between V3 and V4.
+
+### 8.17
+
+- Removed `GET /projects/:search` (use: `GET /projects?search=x`) [!8877](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8877)
+- `iid` filter has been removed from `GET /projects/:id/issues` [!8967](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8967)
+- `GET /projects/:id/merge_requests?iid[]=x&iid[]=y` array filter has been renamed to `iids` [!8793](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8793)
+- Endpoints under `GET /projects/merge_request/:id` have been removed (use: `GET /projects/merge_requests/:id`) [!8793](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8793)
+- Project snippets do not return deprecated field `expires_at` [!8723](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8723)
+- Endpoints under `GET /projects/:id/keys` have been removed (use `GET /projects/:id/deploy_keys`) [!8716](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8716)
+
+### 9.0
+
+- Status 409 returned for `POST /projects/:id/members` when a member already exists [!9093](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9093)
+- Moved `DELETE /projects/:id/star` to `POST /projects/:id/unstar` [!9328](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9328)
+- Removed the following deprecated Templates endpoints (these are still accessible with `/templates` prefix) [!8853](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8853)
+ - `/licences`
+ - `/licences/:key`
+ - `/gitignores`
+ - `/gitlab_ci_ymls`
+ - `/dockerfiles`
+ - `/gitignores/:key`
+ - `/gitlab_ci_ymls/:key`
+ - `/dockerfiles/:key`
+- Moved `POST /projects/fork/:id` to `POST /projects/:id/fork` [!8940](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8940)
+- Moved `DELETE /todos` to `POST /todos/mark_as_done` and `DELETE /todos/:todo_id` to `POST /todos/:todo_id/mark_as_done` [!9410](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9410)
+- Project filters are no longer available as `GET /projects/foo`, but as `GET /projects?foo=true` instead [!8962](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8962)
+ - `GET /projects/visible` & `GET /projects/all` are consolidated into `GET /projects` and can be used with or without authorization
+ - `GET /projects/owned` moved to `GET /projects?owned=true`
+ - `GET /projects/starred` moved to `GET /projects?starred=true`
+- `GET /projects` returns all projects visible to current user, even if the user is not a member [!9674](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9674)
+ - To get projects the user is a member of, use `GET /projects?membership=true`
+- Return pagination headers for all endpoints that return an array [!8606](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8606)
+- Added `POST /environments/:environment_id/stop` to stop an environment [!8808](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8808)
+- Removed `DELETE /projects/:id/deploy_keys/:key_id/disable`. Use `DELETE /projects/:id/deploy_keys/:key_id` instead [!9366](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9366)
+- Moved `PUT /users/:id/(block|unblock)` to `POST /users/:id/(block|unblock)` [!9371](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9371)
+- Make subscription API more RESTful. Use `POST /projects/:id/:subscribable_type/:subscribable_id/subscribe` to subscribe and `POST /projects/:id/:subscribable_type/:subscribable_id/unsubscribe` to unsubscribe from a resource. [!9325](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9325)
+- Labels filter on `GET /projects/:id/issues` and `GET /issues` now matches only issues containing all labels (i.e.: Logical AND, not OR) [!8849](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8849)
+- Renamed param `branch_name` to `branch` on the following endpoints [!8936](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8936)
+ - `POST /projects/:id/repository/branches`
+ - `POST /projects/:id/repository/commits`
+ - `POST/PUT/DELETE :id/repository/files`
+- Renamed the `merge_when_build_succeeds` parameter to `merge_when_pipeline_succeeds` on the following endpoints: [!9335](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/)
+ - `PUT /projects/:id/merge_requests/:merge_request_id/merge`
+ - `POST /projects/:id/merge_requests/:merge_request_id/cancel_merge_when_pipeline_succeeds`
+ - `POST /projects`
+ - `POST /projects/user/:user_id`
+ - `PUT /projects/:id`
+- Renamed `branch_name` to `branch` on `DELETE /projects/:id/repository/branches/:branch` response [!8936](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8936)
+- Remove `public` param from create and edit actions of projects [!8736](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8736)
+- Remove `subscribed` field from responses returning list of issues or merge
+ requests. Fetch individual issues or merge requests to obtain the value
+ of `subscribed`
+ [!9661](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9661)
+- Use `visibility` as string parameter everywhere [!9337](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9337)
+- Notes do not return deprecated field `upvote` and `downvote` [!9384](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9384)
+- Return HTTP status code `400` for all validation errors when creating or updating a member instead of sometimes `422` error. [!9523](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9523)
+- Remove `GET /groups/owned`. Use `GET /groups?owned=true` instead [!9505](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9505)
+- Return 202 with JSON body on async removals on V4 API (`DELETE /projects/:id/repository/merged_branches` and `DELETE /projects/:id`) [!9449](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9449)
+- `GET /projects/:id/milestones?iid[]=x&iid[]=y` array filter has been renamed to `iids` [!9096](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9096)
+- Return basic info about pipeline in `GET /projects/:id/pipelines` [!8875](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8875)
+- Renamed all `build` references to `job` [!9463](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9463)
+- Drop `GET /projects/:id/repository/commits/:sha/jobs` [!9463](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9463)
+- Rename Build Triggers to be Pipeline Triggers API [!9713](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9713)
+ - `POST /projects/:id/trigger/builds` to `POST /projects/:id/trigger/pipeline`
+ - Require description when creating a new trigger `POST /projects/:id/triggers`
+- Simplify project payload exposed on Environment endpoints [!9675](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9675)
+- API uses merge request `IID`s (internal ID, as in the web UI) rather than `ID`s. This affects the merge requests, award emoji, todos, and time tracking APIs. [!9530](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9530)
+- API uses issue `IID`s (internal ID, as in the web UI) rather than `ID`s. This affects the issues, award emoji, todos, and time tracking APIs. [!9530](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9530)
+- Change initial page from `0` to `1` on `GET /projects/:id/repository/commits` (like on the rest of the API) [!9679] (https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9679)
+- Return correct `Link` header data for `GET /projects/:id/repository/commits` [!9679] (https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9679)
+- Update endpoints for repository files [!9637](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9637)
+ - Moved `GET /projects/:id/repository/files?file_path=:file_path` to `GET /projects/:id/repository/files/:file_path` (`:file_path` should be URL-encoded)
+ - `GET /projects/:id/repository/blobs/:sha` now returns JSON attributes for the blob identified by `:sha`, instead of finding the commit identified by `:sha` and returning the raw content of the blob in that commit identified by the required `?filepath=:filepath`
+ - Moved `GET /projects/:id/repository/commits/:sha/blob?file_path=:file_path` and `GET /projects/:id/repository/blobs/:sha?file_path=:file_path` to `GET /projects/:id/repository/files/:file_path/raw?ref=:sha`
+ - `GET /projects/:id/repository/tree` parameter `ref_name` has been renamed to `ref` for consistency
+- `confirm` parameter for `POST /users` has been deprecated in favor of `skip_confirmation` parameter
diff --git a/doc/api/version.md b/doc/api/version.md
new file mode 100644
index 00000000000..8b2a5b51bc5
--- /dev/null
+++ b/doc/api/version.md
@@ -0,0 +1,23 @@
+# Version API
+
+>**Note:** This feature was introduced in GitLab 8.13
+
+Retrieve version information for this GitLab instance. Responds `200 OK` for
+authenticated users.
+
+```
+GET /version
+```
+
+```bash
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/version
+```
+
+Example response:
+
+```json
+{
+ "version": "8.13.0-pre",
+ "revision": "4e963fe"
+}
+```
diff --git a/doc/articles/how_to_configure_ldap_gitlab_ce/img/gitlab_ou.png b/doc/articles/how_to_configure_ldap_gitlab_ce/img/gitlab_ou.png
new file mode 100644
index 00000000000..11ce324f938
--- /dev/null
+++ b/doc/articles/how_to_configure_ldap_gitlab_ce/img/gitlab_ou.png
Binary files differ
diff --git a/doc/articles/how_to_configure_ldap_gitlab_ce/img/ldap_ou.gif b/doc/articles/how_to_configure_ldap_gitlab_ce/img/ldap_ou.gif
new file mode 100644
index 00000000000..a6727a3d85f
--- /dev/null
+++ b/doc/articles/how_to_configure_ldap_gitlab_ce/img/ldap_ou.gif
Binary files differ
diff --git a/doc/articles/how_to_configure_ldap_gitlab_ce/img/user_auth.gif b/doc/articles/how_to_configure_ldap_gitlab_ce/img/user_auth.gif
new file mode 100644
index 00000000000..36e6085259f
--- /dev/null
+++ b/doc/articles/how_to_configure_ldap_gitlab_ce/img/user_auth.gif
Binary files differ
diff --git a/doc/articles/how_to_configure_ldap_gitlab_ce/index.md b/doc/articles/how_to_configure_ldap_gitlab_ce/index.md
new file mode 100644
index 00000000000..6892905dd94
--- /dev/null
+++ b/doc/articles/how_to_configure_ldap_gitlab_ce/index.md
@@ -0,0 +1,266 @@
+# How to configure LDAP with GitLab CE
+
+> **Article [Type](../../development/writing_documentation.html#types-of-technical-articles):** admin guide ||
+> **Level:** intermediary ||
+> **Author:** [Chris Wilson](https://gitlab.com/MrChrisW) ||
+> **Publication date:** 2017/05/03
+
+## Introduction
+
+Managing a large number of users in GitLab can become a burden for system administrators. As an organization grows so do user accounts. Keeping these user accounts in sync across multiple enterprise applications often becomes a time consuming task.
+
+In this guide we will focus on configuring GitLab with Active Directory. [Active Directory](https://en.wikipedia.org/wiki/Active_Directory) is a popular LDAP compatible directory service provided by Microsoft, included in all modern Windows Server operating systems.
+
+GitLab has supported LDAP integration since [version 2.2](https://about.gitlab.com/2012/02/22/gitlab-version-2-2/). With GitLab LDAP [group syncing](#group-syncing-ee) being added to GitLab Enterprise Edition in [version 6.0](https://about.gitlab.com/2013/08/20/gitlab-6-dot-0-released/). LDAP integration has become one of the most popular features in GitLab.
+
+## Getting started
+
+### Choosing an LDAP Server
+
+The main reason organizations choose to utilize a LDAP server is to keep the entire organization's user base consolidated into a central repository. Users can access multiple applications and systems across the IT environment using a single login. Because LDAP is an open, vendor-neutral, industry standard application protocol, the number of applications using LDAP authentication continues to increase.
+
+There are many commercial and open source [directory servers](https://en.wikipedia.org/wiki/Directory_service#LDAP_implementations) that support the LDAP protocol. Deciding on the right directory server highly depends on the existing IT environment in which the server will be integrated with.
+
+For example, [Active Directory](https://technet.microsoft.com/en-us/library/hh831484(v=ws.11).aspx) is generally favored in a primarily Windows environment, as this allows quick integration with existing services. Other popular directory services include:
+
+- [Oracle Internet Directory](http://www.oracle.com/technetwork/middleware/id-mgmt/overview/index-082035.html)
+- [OpenLDAP](http://www.openldap.org/)
+- [389 Directory](http://directory.fedoraproject.org/)
+- [OpenDJ](https://forgerock.org/opendj/)
+- [ApacheDS](https://directory.apache.org/)
+
+> GitLab uses the [Net::LDAP](https://rubygems.org/gems/net-ldap) library under the hood. This means it supports all [IETF](https://tools.ietf.org/html/rfc2251) compliant LDAPv3 servers.
+
+### Active Directory (AD)
+
+We won't cover the installation and configuration of Windows Server or Active Directory Domain Services in this tutorial. There are a number of resources online to guide you through this process:
+
+- Install Windows Server 2012 - (_technet.microsoft.com_) - [Installing Windows Server 2012 ](https://technet.microsoft.com/en-us/library/jj134246(v=ws.11).aspx)
+
+- Install Active Directory Domain Services (AD DS) (_technet.microsoft.com_)- [Install Active Directory Domain Services](https://technet.microsoft.com/windows-server-docs/identity/ad-ds/deploy/install-active-directory-domain-services--level-100-#BKMK_PS)
+
+> **Shortcut:** You can quickly install AD DS via PowerShell using
+`Install-WindowsFeature AD-Domain-Services -IncludeManagementTools`
+
+### Creating an AD **OU** structure
+
+Configuring organizational units (**OU**s) is an important part of setting up Active Directory. **OU**s form the base for an entire organizational structure. Using GitLab as an example we have designed the **OU** structure below using the geographic **OU** model. In the Geographic Model we separate **OU**s for different geographic regions.
+
+| GitLab **OU** Design | GitLab AD Structure |
+| :----------------------------: | :------------------------------: |
+| ![GitLab OU Design][gitlab_ou] | ![GitLab AD Structure][ldap_ou] |
+
+[gitlab_ou]: img/gitlab_ou.png
+[ldap_ou]: img/ldap_ou.gif
+
+Using PowerShell you can output the **OU** structure as a table (_all names are examples only_):
+
+```ps
+Get-ADObject -LDAPFilter "(objectClass=*)" -SearchBase 'OU=GitLab INT,DC=GitLab,DC=org' -Properties CanonicalName | Format-Table Name,CanonicalName -A
+```
+
+```
+OU CanonicalName
+---- -------------
+GitLab INT GitLab.org/GitLab INT
+United States GitLab.org/GitLab INT/United States
+Developers GitLab.org/GitLab INT/United States/Developers
+Gary Johnson GitLab.org/GitLab INT/United States/Developers/Gary Johnson
+Ellis Matthews GitLab.org/GitLab INT/United States/Developers/Ellis Matthews
+William Collins GitLab.org/GitLab INT/United States/Developers/William Collins
+People Ops GitLab.org/GitLab INT/United States/People Ops
+Margaret Baker GitLab.org/GitLab INT/United States/People Ops/Margaret Baker
+Libby Hartzler GitLab.org/GitLab INT/United States/People Ops/Libby Hartzler
+Victoria Ryles GitLab.org/GitLab INT/United States/People Ops/Victoria Ryles
+The Netherlands GitLab.org/GitLab INT/The Netherlands
+Developers GitLab.org/GitLab INT/The Netherlands/Developers
+John Doe GitLab.org/GitLab INT/The Netherlands/Developers/John Doe
+Jon Mealy GitLab.org/GitLab INT/The Netherlands/Developers/Jon Mealy
+Jane Weingarten GitLab.org/GitLab INT/The Netherlands/Developers/Jane Weingarten
+Production GitLab.org/GitLab INT/The Netherlands/Production
+Sarah Konopka GitLab.org/GitLab INT/The Netherlands/Production/Sarah Konopka
+Cynthia Bruno GitLab.org/GitLab INT/The Netherlands/Production/Cynthia Bruno
+David George GitLab.org/GitLab INT/The Netherlands/Production/David George
+United Kingdom GitLab.org/GitLab INT/United Kingdom
+Developers GitLab.org/GitLab INT/United Kingdom/Developers
+Leroy Fox GitLab.org/GitLab INT/United Kingdom/Developers/Leroy Fox
+Christopher Alley GitLab.org/GitLab INT/United Kingdom/Developers/Christopher Alley
+Norris Morita GitLab.org/GitLab INT/United Kingdom/Developers/Norris Morita
+Support GitLab.org/GitLab INT/United Kingdom/Support
+Laura Stanley GitLab.org/GitLab INT/United Kingdom/Support/Laura Stanley
+Nikki Schuman GitLab.org/GitLab INT/United Kingdom/Support/Nikki Schuman
+Harriet Butcher GitLab.org/GitLab INT/United Kingdom/Support/Harriet Butcher
+Global Groups GitLab.org/GitLab INT/Global Groups
+DevelopersNL GitLab.org/GitLab INT/Global Groups/DevelopersNL
+DevelopersUK GitLab.org/GitLab INT/Global Groups/DevelopersUK
+DevelopersUS GitLab.org/GitLab INT/Global Groups/DevelopersUS
+ProductionNL GitLab.org/GitLab INT/Global Groups/ProductionNL
+SupportUK GitLab.org/GitLab INT/Global Groups/SupportUK
+People Ops US GitLab.org/GitLab INT/Global Groups/People Ops US
+Global Admins GitLab.org/GitLab INT/Global Groups/Global Admins
+```
+
+> See [more information](https://technet.microsoft.com/en-us/library/ff730967.aspx) on searching Active Directory with Windows PowerShell from [The Scripting Guys](https://technet.microsoft.com/en-us/scriptcenter/dd901334.aspx)
+
+## GitLab LDAP configuration
+
+The initial configuration of LDAP in GitLab requires changes to the `gitlab.rb` configuration file. Below is an example of a complete configuration using an Active Directory.
+
+The two Active Directory specific values are `active_directory: true` and `uid: 'sAMAccountName'`. `sAMAccountName` is an attribute returned by Active Directory used for GitLab usernames. See the example output from `ldapsearch` for a full list of attributes a "person" object (user) has in **AD** - [`ldapsearch` example](#using-ldapsearch-unix)
+
+> Both group_base and admin_group configuration options are only available in GitLab Enterprise Edition. See [GitLab EE - LDAP Features](#gitlab-enterprise-edition---ldap-features)
+
+### Example `gitlab.rb` LDAP
+
+```
+gitlab_rails['ldap_enabled'] = true
+gitlab_rails['ldap_servers'] = {
+'main' => {
+ 'label' => 'GitLab AD',
+ 'host' => 'ad.example.org',
+ 'port' => 636,
+ 'uid' => 'sAMAccountName',
+ 'method' => 'ssl',
+ 'bind_dn' => 'CN=GitLabSRV,CN=Users,DC=GitLab,DC=org',
+ 'password' => 'Password1',
+ 'active_directory' => true,
+ 'base' => 'OU=GitLab INT,DC=GitLab,DC=org',
+ 'group_base' => 'OU=Global Groups,OU=GitLab INT,DC=GitLab,DC=org',
+ 'admin_group' => 'Global Admins'
+ }
+}
+```
+
+> **Note:** Remember to run `gitlab-ctl reconfigure` after modifying `gitlab.rb`
+
+## Security improvements (LDAPS)
+
+Security is an important aspect when deploying an LDAP server. By default, LDAP traffic is transmitted unsecured. LDAP can be secured using SSL/TLS called LDAPS, or commonly "LDAP over SSL".
+
+Securing LDAP (enabling LDAPS) on Windows Server 2012 involves installing a valid SSL certificate. For full details see Microsoft's guide [How to enable LDAP over SSL with a third-party certification authority](https://support.microsoft.com/en-us/help/321051/how-to-enable-ldap-over-ssl-with-a-third-party-certification-authority)
+
+> By default a LDAP service listens for connections on TCP and UDP port 389. LDAPS (LDAP over SSL) listens on port 636
+
+### Testing you AD server
+
+#### Using **AdFind** (Windows)
+
+You can use the [`AdFind`](https://social.technet.microsoft.com/wiki/contents/articles/7535.adfind-command-examples.aspx) utility (on Windows based systems) to test that your LDAP server is accessible and authentication is working correctly. This is a freeware utility built by [Joe Richards](http://www.joeware.net/freetools/tools/adfind/index.htm).
+
+**Return all objects**
+
+You can use the filter `objectclass=*` to return all directory objects.
+
+```sh
+adfind -h ad.example.org:636 -ssl -u "CN=GitLabSRV,CN=Users,DC=GitLab,DC=org" -up Password1 -b "OU=GitLab INT,DC=GitLab,DC=org" -f (objectClass=*)
+```
+
+**Return single object using filter**
+
+You can also retrieve a single object by **specifying** the object name or full **DN**. In this example we specify the object name only `CN=Leroy Fox`.
+
+```sh
+adfind -h ad.example.org:636 -ssl -u "CN=GitLabSRV,CN=Users,DC=GitLab,DC=org" -up Password1 -b "OU=GitLab INT,DC=GitLab,DC=org" -f (&(objectcategory=person)(CN=Leroy Fox))”
+```
+
+#### Using **ldapsearch** (Unix)
+
+You can use the `ldapsearch` utility (on Unix based systems) to test that your LDAP server is accessible and authentication is working correctly. This utility is included in the [`ldap-utils`](https://wiki.debian.org/LDAP/LDAPUtils) package.
+
+**Return all objects**
+
+You can use the filter `objectclass=*` to return all directory objects.
+
+```sh
+ldapsearch -D "CN=GitLabSRV,CN=Users,DC=GitLab,DC=org" \
+-w Password1 -p 636 -h ad.example.org \
+-b "OU=GitLab INT,DC=GitLab,DC=org" -Z \
+-s sub "(objectclass=*)"
+```
+
+**Return single object using filter**
+
+You can also retrieve a single object by **specifying** the object name or full **DN**. In this example we specify the object name only `CN=Leroy Fox`.
+
+```sh
+ldapsearch -D "CN=GitLabSRV,CN=Users,DC=GitLab,DC=org" -w Password1 -p 389 -h ad.example.org -b "OU=GitLab INT,DC=GitLab,DC=org" -Z -s sub "CN=Leroy Fox"
+```
+
+**Full output of `ldapsearch` command:** - Filtering for _CN=Leroy Fox_
+
+```
+# LDAPv3
+# base <OU=GitLab INT,DC=GitLab,DC=org> with scope subtree
+# filter: CN=Leroy Fox
+# requesting: ALL
+#
+
+# Leroy Fox, Developers, United Kingdom, GitLab INT, GitLab.org
+dn: CN=Leroy Fox,OU=Developers,OU=United Kingdom,OU=GitLab INT,DC=GitLab,DC=or
+ g
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: user
+cn: Leroy Fox
+sn: Fox
+givenName: Leroy
+distinguishedName: CN=Leroy Fox,OU=Developers,OU=United Kingdom,OU=GitLab INT,
+ DC=GitLab,DC=org
+instanceType: 4
+whenCreated: 20170210030500.0Z
+whenChanged: 20170213050128.0Z
+displayName: Leroy Fox
+uSNCreated: 16790
+memberOf: CN=DevelopersUK,OU=Global Groups,OU=GitLab INT,DC=GitLab,DC=org
+uSNChanged: 20812
+name: Leroy Fox
+objectGUID:: rBCAo6NR6E6vfSKgzcUILg==
+userAccountControl: 512
+badPwdCount: 0
+codePage: 0
+countryCode: 0
+badPasswordTime: 0
+lastLogoff: 0
+lastLogon: 0
+pwdLastSet: 131311695009850084
+primaryGroupID: 513
+objectSid:: AQUAAAAAAAUVAAAA9GMAb7tdJZvsATf7ZwQAAA==
+accountExpires: 9223372036854775807
+logonCount: 0
+sAMAccountName: Leroyf
+sAMAccountType: 805306368
+userPrincipalName: Leroyf@GitLab.org
+objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=GitLab,DC=org
+dSCorePropagationData: 16010101000000.0Z
+lastLogonTimestamp: 131314356887754250
+
+# search result
+search: 2
+result: 0 Success
+
+# numResponses: 2
+# numEntries: 1
+```
+
+## Basic user authentication
+
+After configuring LDAP, basic authentication will be available. Users can then login using their directory credentials. An extra tab is added to the GitLab login screen for the configured LDAP server (e.g "**GitLab AD**").
+
+![GitLab OU Structure](img/user_auth.gif)
+
+Users that are removed from the LDAP base group (e.g `OU=GitLab INT,DC=GitLab,DC=org`) will be **blocked** in GitLab. [More information](../../administration/auth/ldap.md#security) on LDAP security.
+
+If `allow_username_or_email_login` is enabled in the LDAP configuration, GitLab will ignore everything after the first '@' in the LDAP username used on login. Example: The username `jon.doe@example.com` is converted to `jon.doe` when authenticating with the LDAP server. Disable this setting if you use `userPrincipalName` as the `uid`.
+
+## LDAP extended features on GitLab EE
+
+With [GitLab Enterprise Edition (EE)](https://about.gitlab.com/giltab-ee/), besides everything we just described, you'll
+have extended functionalities with LDAP, such as:
+
+- Group sync
+- Group permissions
+- Updating user permissions
+- Multiple LDAP servers
+
+Read through the article on [LDAP for GitLab EE](https://docs.gitlab.com/ee/articles/how_to_configure_ldap_gitlab_ee/) for an overview.
diff --git a/doc/articles/how_to_install_git/index.md b/doc/articles/how_to_install_git/index.md
new file mode 100644
index 00000000000..66d866b2d09
--- /dev/null
+++ b/doc/articles/how_to_install_git/index.md
@@ -0,0 +1,66 @@
+# Installing Git
+
+> **Article [Type](../../development/writing_documentation.html#types-of-technical-articles):** user guide ||
+> **Level:** beginner ||
+> **Author:** [Sean Packham](https://gitlab.com/SeanPackham) ||
+> **Publication date:** 2017/05/15
+
+To begin contributing to GitLab projects
+you will need to install the Git client on your computer.
+This article will show you how to install Git on macOS, Ubuntu Linux and Windows.
+
+## Install Git on macOS using the Homebrew package manager
+
+Although it is easy to use the version of Git shipped with macOS
+or install the latest version of Git on macOS by downloading it from the project website,
+we recommend installing it via Homebrew to get access to
+an extensive selection of dependancy managed libraries and applications.
+
+If you are sure you don't need access to any additional development libraries
+or don't have approximately 15gb of available disk space for Xcode and Homebrew
+use one of the the aforementioned methods.
+
+### Installing Xcode
+
+Xcode is needed by Homebrew to build dependencies.
+You can install [XCode](https://developer.apple.com/xcode/)
+through the macOS App Store.
+
+### Installing Homebrew
+
+Once Xcode is installed browse to the [Homebrew website](http://brew.sh/index.html)
+for the official Homebrew installation instructions.
+
+### Installing Git via Homebrew
+
+With Homebrew installed you are now ready to install Git.
+Open a Terminal and enter in the following command:
+
+```bash
+brew install git
+```
+
+Congratulations you should now have Git installed via Homebrew.
+Next read our article on [adding an SSH key to GitLab](../../ssh/README.md).
+
+## Install Git on Ubuntu Linux
+
+On Ubuntu and other Linux operating systems
+it is recommended to use the built in package manager to install Git.
+
+Open a Terminal and enter in the following commands
+to install the latest Git from the official Git maintained package archives:
+
+```bash
+sudo apt-add-repository ppa:git-core/ppa
+sudo apt-get update
+sudo apt-get install git
+```
+
+Congratulations you should now have Git installed via the Ubuntu package manager.
+Next read our article on [adding an SSH key to GitLab](../../ssh/README.md).
+
+## Installing Git on Windows from the Git website
+
+Browse to the [Git website](https://git-scm.com/) and download and install Git for Windows.
+Next read our article on [adding an SSH key to GitLab](../../ssh/README.md).
diff --git a/doc/articles/index.md b/doc/articles/index.md
new file mode 100644
index 00000000000..342fa88e80f
--- /dev/null
+++ b/doc/articles/index.md
@@ -0,0 +1,25 @@
+# Technical Articles
+
+[Technical Articles](../development/writing_documentation.md#technical-articles) are
+topic-related documentation, written with an user-friendly approach and language, aiming
+to provide the community with guidance on specific processes to achieve certain objectives.
+
+They are written by members of the GitLab Team and by
+[Community Writers](https://about.gitlab.com/handbook/product/technical-writing/community-writers/).
+
+## Authentication
+
+- **LDAP**
+ - [How to configure LDAP with GitLab CE](how_to_configure_ldap_gitlab_ce/index.md)
+
+## Git
+
+- [How to install Git](how_to_install_git/index.md)
+
+## GitLab Pages
+
+- **GitLab Pages from A to Z**
+ - [Part 1: Static sites and GitLab Pages domains](../user/project/pages/getting_started_part_one.md)
+ - [Part 2: Quick start guide - Setting up GitLab Pages](../user/project/pages/getting_started_part_two.md)
+ - [Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](../user/project/pages/getting_started_part_three.md)
+ - [Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](../user/project/pages/getting_started_part_four.md)
diff --git a/doc/ci/README.md b/doc/ci/README.md
index 341bc85a16a..ca7266ac68f 100644
--- a/doc/ci/README.md
+++ b/doc/ci/README.md
@@ -1,22 +1,148 @@
-## GitLab CI Documentation
+# GitLab Continuous Integration (GitLab CI)
-### CI User documentation
+![Pipeline graph](img/cicd_pipeline_infograph.png)
+
+The benefits of Continuous Integration are huge when automation plays an
+integral part of your workflow. GitLab comes with built-in Continuous
+Integration, Continuous Deployment, and Continuous Delivery support to build,
+test, and deploy your application.
+
+Here's some info we've gathered to get you started.
+
+## Getting started
+
+The first steps towards your GitLab CI journey.
+
+- [Getting started with GitLab CI](quick_start/README.md)
+- [Pipelines and jobs](pipelines.md)
+- [Configure a Runner, the application that runs your jobs](runners/README.md)
+- **Articles:**
+ - [Getting started with GitLab and GitLab CI - Intro to CI](https://about.gitlab.com/2015/12/14/getting-started-with-gitlab-and-gitlab-ci/)
+ - [Continuous Integration, Delivery, and Deployment with GitLab - Intro to CI/CD](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/)
+ - [GitLab CI: Run jobs sequentially, in parallel, or build a custom pipeline](https://about.gitlab.com/2016/07/29/the-basics-of-gitlab-ci/)
+ - [Setting up GitLab Runner For Continuous Integration](https://about.gitlab.com/2016/03/01/gitlab-runner-with-docker/)
+ - [GitLab CI: Deployment & environments](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/)
+- **Videos:**
+ - [Demo (March, 2017): how to get started using CI/CD with GitLab](https://about.gitlab.com/2017/03/13/ci-cd-demo/)
+ - [Webcast (April, 2016): getting started with CI in GitLab](https://about.gitlab.com/2016/04/20/webcast-recording-and-slides-introduction-to-ci-in-gitlab/)
+- **Third-party videos:**
+ - [Intégration continue avec GitLab (September, 2016)](https://www.youtube.com/watch?v=URcMBXjIr24&t=13s)
+ - [GitLab CI for Minecraft Plugins (July, 2016)](https://www.youtube.com/watch?v=Z4pcI9F8yf8)
+
+## Reference guides
+
+Once you get familiar with the getting started guides, you'll find yourself
+digging into specific reference guides.
+
+- [`.gitlab-ci.yml` reference](yaml/README.md) - Learn all about the ins and
+ outs of `.gitlab-ci.yml` definitions
+- [CI Variables](variables/README.md) - Learn how to use variables defined in
+ your `.gitlab-ci.yml` or secured ones defined in your project's settings
+- **The permissions model** - Learn about the access levels a user can have for
+ performing certain CI actions
+ - [User permissions](../user/permissions.md#gitlab-ci)
+ - [Jobs permissions](../user/permissions.md#jobs-permissions)
+
+## GitLab CI + Docker
+
+Leverage the power of Docker to run your CI pipelines.
-- [Get started with GitLab CI](quick_start/README.md)
-- [CI examples for various languages](examples/README.md)
-- [Learn how to enable or disable GitLab CI](enable_or_disable_ci.md)
-- [Pipelines and builds](pipelines.md)
-- [Environments and deployments](environments.md)
-- [Learn how `.gitlab-ci.yml` works](yaml/README.md)
-- [Configure a Runner, the application that runs your builds](runners/README.md)
- [Use Docker images with GitLab Runner](docker/using_docker_images.md)
- [Use CI to build Docker images](docker/using_docker_build.md)
-- [Use variables in your `.gitlab-ci.yml`](variables/README.md)
+- [CI services (linked Docker containers)](services/README.md)
+- **Articles:**
+ - [Setting up GitLab Runner For Continuous Integration](https://about.gitlab.com/2016/03/01/gitlab-runner-with-docker/)
+
+## Advanced use
+
+Once you get familiar with the basics of GitLab CI, it's time to dive in and
+learn how to leverage its potential even more.
+
+- [Environments and deployments](environments.md) - Separate your jobs into
+ environments and use them for different purposes like testing, building and
+ deploying
+- [Job artifacts](../user/project/pipelines/job_artifacts.md)
+- [Git submodules](git_submodules.md) - How to run your CI jobs when Git
+ submodules are involved
+- [Auto deploy](autodeploy/index.md)
- [Use SSH keys in your build environment](ssh_keys/README.md)
-- [Trigger builds through the API](triggers/README.md)
-- [Build artifacts](../user/project/builds/artifacts.md)
-- [User permissions](../user/permissions.md#gitlab-ci)
-- [Build permissions](../user/permissions.md#build-permissions)
-- [API](../api/ci/README.md)
-- [CI services (linked docker containers)](services/README.md)
-- [**New CI build permissions model**](../user/project/new_ci_build_permissions_model.md) Read about what changed in GitLab 8.12 and how that affects your builds. There's a new way to access your Git submodules and LFS objects in builds.
+- [Trigger pipelines through the GitLab API](triggers/README.md)
+- [Trigger pipelines on a schedule](../user/project/pipelines/schedules.md)
+
+## Review Apps
+
+- [Review Apps](review_apps/index.md)
+- **Articles:**
+ - [Introducing Review Apps](https://about.gitlab.com/2016/11/22/introducing-review-apps/)
+ - [Example project that shows how to use Review Apps](https://gitlab.com/gitlab-examples/review-apps-nginx/)
+
+## GitLab CI for GitLab Pages
+
+See the topic on [GitLab Pages](../user/project/pages/index.md).
+
+## Special configuration
+
+You can change the default behavior of GitLab CI in your whole GitLab instance
+as well as in each project.
+
+- **Project specific**
+ - [Pipelines settings](../user/project/pipelines/settings.md)
+ - [Learn how to enable or disable GitLab CI](enable_or_disable_ci.md)
+- **Affecting the whole GitLab instance**
+ - [Continuous Integration admin settings](../user/admin_area/settings/continuous_integration.md)
+
+## Examples
+
+>**Note:**
+A collection of `.gitlab-ci.yml` files is maintained at the
+[GitLab CI Yml project][gitlab-ci-templates].
+If your favorite programming language or framework is missing we would love
+your help by sending a merge request with a `.gitlab-ci.yml`.
+
+Here is an collection of tutorials and guides on setting up your CI pipeline.
+
+- [GitLab CI examples](examples/README.md) for the following languages and frameworks:
+ - [PHP](examples/php.md)
+ - [Ruby](examples/test-and-deploy-ruby-application-to-heroku.md)
+ - [Python](examples/test-and-deploy-python-application-to-heroku.md)
+ - [Clojure](examples/test-clojure-application.md)
+ - [Scala](examples/test-scala-application.md)
+ - [Phoenix](examples/test-phoenix-application.md)
+ - [Run PHP Composer & NPM scripts then deploy them to a staging server](examples/deployment/composer-npm-deploy.md)
+ - [Analyze code quality with the Code Climate CLI](examples/code_climate.md)
+- **Blog posts**
+ - [Automated Debian packaging](https://about.gitlab.com/2016/10/12/automated-debian-package-build-with-gitlab-ci/)
+ - [Spring boot application with GitLab CI and Kubernetes](https://about.gitlab.com/2016/12/14/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/)
+ - [Setting up GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/)
+ - [Setting up GitLab CI for Android projects](https://about.gitlab.com/2016/11/30/setting-up-gitlab-ci-for-android-projects/)
+ - [Building a new GitLab Docs site with Nanoc, GitLab CI, and GitLab Pages](https://about.gitlab.com/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/)
+ - [CI/CD with GitLab in action](https://about.gitlab.com/2017/03/13/ci-cd-demo/)
+ - [Building an Elixir Release into a Docker image using GitLab CI](https://about.gitlab.com/2016/08/11/building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1/)
+- **Miscellaneous**
+ - [Using `dpl` as deployment tool](examples/deployment/README.md)
+ - [Repositories with examples for various languages](https://gitlab.com/groups/gitlab-examples)
+ - [The .gitlab-ci.yml file for GitLab itself](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml)
+ - [Example project that shows how to use Review Apps](https://gitlab.com/gitlab-examples/review-apps-nginx/)
+
+## Integrations
+
+- **Articles:**
+ - [Continuous Delivery with GitLab and Convox](https://about.gitlab.com/2016/06/09/continuous-delivery-with-gitlab-and-convox/)
+ - [Getting Started with GitLab and Shippable Continuous Integration](https://about.gitlab.com/2016/05/05/getting-started-gitlab-and-shippable/)
+ - [GitLab Partners with DigitalOcean to make Continuous Integration faster, safer, and more affordable](https://about.gitlab.com/2016/04/19/gitlab-partners-with-digitalocean-to-make-continuous-integration-faster-safer-and-more-affordable/)
+
+## Why GitLab CI?
+
+- **Articles:**
+ - [Why We Chose GitLab CI for our CI/CD Solution](https://about.gitlab.com/2016/10/17/gitlab-ci-oohlala/)
+ - [Building our web-app on GitLab CI: 5 reasons why Captain Train migrated from Jenkins to GitLab CI](https://about.gitlab.com/2016/07/22/building-our-web-app-on-gitlab-ci/)
+
+## Breaking changes
+
+- [CI variables renaming for GitLab 9.0](variables/README.md#9-0-renaming) Read about the
+ deprecated CI variables and what you should use for GitLab 9.0+.
+- [New CI job permissions model](../user/project/new_ci_build_permissions_model.md)
+ Read about what changed in GitLab 8.12 and how that affects your jobs.
+ There's a new way to access your Git submodules and LFS objects in jobs.
+
+[gitlab-ci-templates]: https://gitlab.com/gitlab-org/gitlab-ci-yml
diff --git a/doc/ci/api/README.md b/doc/ci/api/README.md
index 4ca8d92d7cc..98f37935427 100644
--- a/doc/ci/api/README.md
+++ b/doc/ci/api/README.md
@@ -1,3 +1 @@
-# GitLab CI API
-
This document was moved to a [new location](../../api/ci/README.md).
diff --git a/doc/ci/api/builds.md b/doc/ci/api/builds.md
index f5bd3181c02..0563a367609 100644
--- a/doc/ci/api/builds.md
+++ b/doc/ci/api/builds.md
@@ -1,3 +1 @@
-# Builds API
-
This document was moved to a [new location](../../api/ci/builds.md).
diff --git a/doc/ci/api/runners.md b/doc/ci/api/runners.md
index b14ea99db76..1027363851c 100644
--- a/doc/ci/api/runners.md
+++ b/doc/ci/api/runners.md
@@ -1,3 +1 @@
-# Runners API
-
This document was moved to a [new location](../../api/ci/runners.md).
diff --git a/doc/ci/autodeploy/img/auto_deploy_button.png b/doc/ci/autodeploy/img/auto_deploy_button.png
new file mode 100644
index 00000000000..423e76a6cda
--- /dev/null
+++ b/doc/ci/autodeploy/img/auto_deploy_button.png
Binary files differ
diff --git a/doc/ci/autodeploy/img/auto_deploy_dropdown.png b/doc/ci/autodeploy/img/auto_deploy_dropdown.png
new file mode 100644
index 00000000000..b93b0a08fea
--- /dev/null
+++ b/doc/ci/autodeploy/img/auto_deploy_dropdown.png
Binary files differ
diff --git a/doc/ci/autodeploy/index.md b/doc/ci/autodeploy/index.md
new file mode 100644
index 00000000000..9fa2b2c4969
--- /dev/null
+++ b/doc/ci/autodeploy/index.md
@@ -0,0 +1,71 @@
+# Auto deploy
+
+> [Introduced][mr-8135] in GitLab 8.15.
+> Auto deploy is an experimental feature and is not recommended for Production use at this time.
+> As of GitLab 9.1, access to the container registry is only available while the Pipeline is running. Restarting a pod, scaling a service, or other actions which require on-going access will fail. On-going secure access is planned for a subsequent release.
+
+Auto deploy is an easy way to configure GitLab CI for the deployment of your
+application. GitLab Community maintains a list of `.gitlab-ci.yml`
+templates for various infrastructure providers and deployment scripts
+powering them. These scripts are responsible for packaging your application,
+setting up the infrastructure and spinning up necessary services (for
+example a database).
+
+You can use [project services][project-services] to store credentials to
+your infrastructure provider and they will be available during the
+deployment.
+
+## Supported templates
+
+The list of supported auto deploy templates is available in the
+[gitlab-ci-yml project][auto-deploy-templates].
+
+## Configuration
+
+1. Enable a deployment [project service][project-services] to store your
+credentials. For example, if you want to deploy to OpenShift you have to
+enable [Kubernetes service][kubernetes-service].
+1. Configure GitLab Runner to use Docker or Kubernetes executor with
+[privileged mode enabled][docker-in-docker].
+1. Navigate to the "Project" tab and click "Set up auto deploy" button.
+ ![Auto deploy button](img/auto_deploy_button.png)
+1. Select a template.
+ ![Dropdown with auto deploy templates](img/auto_deploy_dropdown.png)
+1. Commit your changes and create a merge request.
+1. Test your deployment configuration using a [Review App][review-app] that was
+created automatically for you.
+
+## Private Project Support
+
+> Experimental support [introduced][mr-2] in GitLab 9.1.
+
+When a project has been marked as private, GitLab's [Container Registry][container-registry] requires authentication when downloading containers. Auto deploy will automatically provide the required authentication information to Kubernetes, allowing temporary access to the registry. Authentication credentials will be valid while the pipeline is running, allowing for a successful initial deployment.
+
+After the pipeline completes, Kubernetes will no longer be able to access the container registry. Restarting a pod, scaling a service, or other actions which require on-going access to the registry will fail. On-going secure access is planned for a subsequent release.
+
+## PostgreSQL Database Support
+
+> Experimental support [introduced][mr-8] in GitLab 9.1.
+
+In order to support applications that require a database, [PostgreSQL][postgresql] is provisioned by default. Credentials to access the database are preconfigured, but can be customized by setting the associated [variables](#postgresql-variables). These credentials can be used for defining a `DATABASE_URL` of the format: `postgres://user:password@postgres-host:postgres-port/postgres-database`. It is important to note that the database itself is temporary, and contents will be not be saved.
+
+PostgreSQL provisioning can be disabled by setting the variable `DISABLE_POSTGRES` to `"yes"`.
+
+### PostgreSQL Variables
+
+1. `DISABLE_POSTGRES: "yes"`: disable automatic deployment of PostgreSQL
+1. `POSTGRES_USER: "my-user"`: use custom username for PostgreSQL
+1. `POSTGRES_PASSWORD: "password"`: use custom password for PostgreSQL
+1. `POSTGRES_DB: "my database"`: use custom database name for PostgreSQL
+
+[mr-8135]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8135
+[mr-2]: https://gitlab.com/gitlab-examples/kubernetes-deploy/merge_requests/2
+[mr-8]: https://gitlab.com/gitlab-examples/kubernetes-deploy/merge_requests/8
+[project-settings]: https://docs.gitlab.com/ce/public_access/public_access.html
+[project-services]: ../../user/project/integrations/project_services.md
+[auto-deploy-templates]: https://gitlab.com/gitlab-org/gitlab-ci-yml/tree/master/autodeploy
+[kubernetes-service]: ../../user/project/integrations/kubernetes.md
+[docker-in-docker]: ../docker/using_docker_build.md#use-docker-in-docker-executor
+[review-app]: ../review_apps/index.md
+[container-registry]: https://docs.gitlab.com/ce/user/project/container_registry.html
+[postgresql]: https://www.postgresql.org/
diff --git a/doc/ci/build_artifacts/README.md b/doc/ci/build_artifacts/README.md
index 05605f10fb4..22b3872025f 100644
--- a/doc/ci/build_artifacts/README.md
+++ b/doc/ci/build_artifacts/README.md
@@ -1,4 +1 @@
-This document was moved to:
-
-- [user/project/builds/artifacts.md](../../user/project/builds/artifacts.md) - user guide
-- [administration/build_artifacts.md](../../administration/build_artifacts.md) - administrator guide
+This document was moved to [pipelines/job_artifacts.md](../../user/project/pipelines/job_artifacts.md).
diff --git a/doc/ci/docker/README.md b/doc/ci/docker/README.md
index 84eaf29efd1..99669a9272a 100644
--- a/doc/ci/docker/README.md
+++ b/doc/ci/docker/README.md
@@ -1,4 +1,4 @@
# Docker integration
-+ [Using Docker Images](using_docker_images.md)
-+ [Using Docker Build](using_docker_build.md) \ No newline at end of file
+- [Using Docker Images](using_docker_images.md)
+- [Using Docker Build](using_docker_build.md)
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index 0f64137a8a9..f7c2a0ef0ca 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -12,6 +12,7 @@ One of the new trends in Continuous Integration/Deployment is to:
1. deploy to a server from the pushed image.
It's also useful when your application already has the `Dockerfile` that can be used to create and test an image:
+
```bash
$ docker build -t my-image dockerfiles/
$ docker run my-docker-image /script/to/run/tests
@@ -19,24 +20,24 @@ $ docker tag my-image my-registry:5000/my-image
$ docker push my-registry:5000/my-image
```
-This requires special configuration of GitLab Runner to enable `docker` support during builds.
+This requires special configuration of GitLab Runner to enable `docker` support during jobs.
## Runner Configuration
-There are three methods to enable the use of `docker build` and `docker run` during builds; each with their own tradeoffs.
+There are three methods to enable the use of `docker build` and `docker run` during jobs; each with their own tradeoffs.
### Use shell executor
The simplest approach is to install GitLab Runner in `shell` execution mode.
-GitLab Runner then executes build scripts as the `gitlab-runner` user.
+GitLab Runner then executes job scripts as the `gitlab-runner` user.
1. Install [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/#installation).
-1. During GitLab Runner installation select `shell` as method of executing build scripts or use command:
+1. During GitLab Runner installation select `shell` as method of executing job scripts or use command:
```bash
- $ sudo gitlab-ci-multi-runner register -n \
- --url https://gitlab.com/ci \
+ sudo gitlab-ci-multi-runner register -n \
+ --url https://gitlab.com/ \
--registration-token REGISTRATION_TOKEN \
--executor shell \
--description "My Runner"
@@ -44,21 +45,23 @@ GitLab Runner then executes build scripts as the `gitlab-runner` user.
2. Install Docker Engine on server.
- For more information how to install Docker Engine on different systems checkout the [Supported installations](https://docs.docker.com/engine/installation/).
+ For more information how to install Docker Engine on different systems
+ checkout the [Supported installations](https://docs.docker.com/engine/installation/).
3. Add `gitlab-runner` user to `docker` group:
```bash
- $ sudo usermod -aG docker gitlab-runner
+ sudo usermod -aG docker gitlab-runner
```
4. Verify that `gitlab-runner` has access to Docker:
```bash
- $ sudo -u gitlab-runner -H docker info
+ sudo -u gitlab-runner -H docker info
```
You can now verify that everything works by adding `docker info` to `.gitlab-ci.yml`:
+
```yaml
before_script:
- docker info
@@ -79,19 +82,19 @@ For more information please read [On Docker security: `docker` group considered
The second approach is to use the special docker-in-docker (dind)
[Docker image](https://hub.docker.com/_/docker/) with all tools installed
-(`docker` and `docker-compose`) and run the build script in context of that
+(`docker` and `docker-compose`) and run the job script in context of that
image in privileged mode.
In order to do that, follow the steps:
-1. Install [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/#installation).
+1. Install [GitLab Runner](https://docs.gitlab.com/runner/install).
1. Register GitLab Runner from the command line to use `docker` and `privileged`
mode:
```bash
sudo gitlab-ci-multi-runner register -n \
- --url https://gitlab.com/ci \
+ --url https://gitlab.com/ \
--registration-token REGISTRATION_TOKEN \
--executor docker \
--description "My Docker Runner" \
@@ -109,7 +112,7 @@ In order to do that, follow the steps:
```
[[runners]]
- url = "https://gitlab.com/ci"
+ url = "https://gitlab.com/"
token = TOKEN
executor = "docker"
[runners.docker]
@@ -122,11 +125,17 @@ In order to do that, follow the steps:
Insecure = false
```
-1. You can now use `docker` in the build script (note the inclusion of the `docker:dind` service):
+1. You can now use `docker` in the build script (note the inclusion of the
+ `docker:dind` service):
```yaml
image: docker:latest
+ # When using dind, it's wise to use the overlayfs driver for
+ # improved performance.
+ variables:
+ DOCKER_DRIVER: overlay
+
services:
- docker:dind
@@ -140,15 +149,21 @@ In order to do that, follow the steps:
- docker run my-docker-image /script/to/run/tests
```
-Docker-in-Docker works well, and is the recommended configuration, but it is not without its own challenges:
-* By enabling `--docker-privileged`, you are effectively disabling all of
-the security mechanisms of containers and exposing your host to privilege
-escalation which can lead to container breakout. For more information, check out the official Docker documentation on
-[Runtime privilege and Linux capabilities][docker-cap].
-* Using docker-in-docker, each build is in a clean environment without the past
-history. Concurrent builds work fine because every build gets it's own instance of docker engine so they won't conflict with each other. But this also means builds can be slower because there's no caching of layers.
-* By default, `docker:dind` uses `--storage-driver vfs` which is the slowest form
-offered.
+Docker-in-Docker works well, and is the recommended configuration, but it is
+not without its own challenges:
+
+- By enabling `--docker-privileged`, you are effectively disabling all of
+ the security mechanisms of containers and exposing your host to privilege
+ escalation which can lead to container breakout. For more information, check
+ out the official Docker documentation on
+ [Runtime privilege and Linux capabilities][docker-cap].
+- When using docker-in-docker, each job is in a clean environment without the past
+ history. Concurrent jobs work fine because every build gets it's own
+ instance of Docker engine so they won't conflict with each other. But this
+ also means jobs can be slower because there's no caching of layers.
+- By default, `docker:dind` uses `--storage-driver vfs` which is the slowest
+ form offered. To use a different driver, see
+ [Using the overlayfs driver](#using-the-overlayfs-driver).
An example project using this approach can be found here: https://gitlab.com/gitlab-examples/docker.
@@ -158,13 +173,13 @@ The third approach is to bind-mount `/var/run/docker.sock` into the container so
In order to do that, follow the steps:
-1. Install [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/#installation).
+1. Install [GitLab Runner](https://docs.gitlab.com/runner/install).
1. Register GitLab Runner from the command line to use `docker` and share `/var/run/docker.sock`:
```bash
sudo gitlab-ci-multi-runner register -n \
- --url https://gitlab.com/ci \
+ --url https://gitlab.com/ \
--registration-token REGISTRATION_TOKEN \
--executor docker \
--description "My Docker Runner" \
@@ -174,13 +189,15 @@ In order to do that, follow the steps:
The above command will register a new Runner to use the special
`docker:latest` image which is provided by Docker. **Notice that it's using
- the Docker daemon of the Runner itself, and any containers spawned by docker commands will be siblings of the Runner rather than children of the runner.** This may have complications and limitations that are unsuitable for your workflow.
+ the Docker daemon of the Runner itself, and any containers spawned by docker
+ commands will be siblings of the Runner rather than children of the runner.**
+ This may have complications and limitations that are unsuitable for your workflow.
The above command will create a `config.toml` entry similar to this:
```
[[runners]]
- url = "https://gitlab.com/ci"
+ url = "https://gitlab.com/"
token = REGISTRATION_TOKEN
executor = "docker"
[runners.docker]
@@ -188,12 +205,13 @@ In order to do that, follow the steps:
image = "docker:latest"
privileged = false
disable_cache = false
- volumes = ["/var/run/docker.sock", "/cache"]
+ volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
[runners.cache]
Insecure = false
```
-1. You can now use `docker` in the build script (note that you don't need to include the `docker:dind` service as when using the Docker in Docker executor):
+1. You can now use `docker` in the build script (note that you don't need to
+ include the `docker:dind` service as when using the Docker in Docker executor):
```yaml
image: docker:latest
@@ -208,27 +226,70 @@ In order to do that, follow the steps:
- docker run my-docker-image /script/to/run/tests
```
-While the above method avoids using Docker in privileged mode, you should be aware of the following implications:
-* By sharing the docker daemon, you are effectively disabling all
-the security mechanisms of containers and exposing your host to privilege
-escalation which can lead to container breakout. For example, if a project
-ran `docker rm -f $(docker ps -a -q)` it would remove the GitLab Runner
-containers.
-* Concurrent builds may not work; if your tests
-create containers with specific names, they may conflict with each other.
-* Sharing files and directories from the source repo into containers may not
-work as expected since volume mounting is done in the context of the host
-machine, not the build container.
-e.g. `docker run --rm -t -i -v $(pwd)/src:/home/app/src test-image:latest run_app_tests`
+While the above method avoids using Docker in privileged mode, you should be
+aware of the following implications:
-## Using the GitLab Container Registry
+- By sharing the docker daemon, you are effectively disabling all
+ the security mechanisms of containers and exposing your host to privilege
+ escalation which can lead to container breakout. For example, if a project
+ ran `docker rm -f $(docker ps -a -q)` it would remove the GitLab Runner
+ containers.
+- Concurrent jobs may not work; if your tests
+ create containers with specific names, they may conflict with each other.
+- Sharing files and directories from the source repo into containers may not
+ work as expected since volume mounting is done in the context of the host
+ machine, not the build container, e.g.:
-> **Note:**
-This feature requires GitLab 8.8 and GitLab Runner 1.2.
+ ```
+ docker run --rm -t -i -v $(pwd)/src:/home/app/src test-image:latest run_app_tests
+ ```
+
+## Using the OverlayFS driver
+
+By default, when using `docker:dind`, Docker uses the `vfs` storage driver which
+copies the filesystem on every run. This is a very disk-intensive operation
+which can be avoided if a different driver is used, for example `overlay`.
-Once you've built a Docker image, you can push it up to the built-in [GitLab Container Registry](../../container_registry/README.md). For example, if you're using
-docker-in-docker on your runners, this is how your `.gitlab-ci.yml` could look:
+1. Make sure a recent kernel is used, preferably `>= 4.2`.
+1. Check whether the `overlay` module is loaded:
+
+ ```
+ sudo lsmod | grep overlay
+ ```
+
+ If you see no result, then it isn't loaded. To load it use:
+
+ ```
+ sudo modprobe overlay
+ ```
+
+ If everything went fine, you need to make sure module is loaded on reboot.
+ On Ubuntu systems, this is done by editing `/etc/modules`. Just add the
+ following line into it:
+
+ ```
+ overlay
+ ```
+1. Use the driver by defining a variable at the top of your `.gitlab-ci.yml`:
+
+ ```
+ variables:
+ DOCKER_DRIVER: overlay
+ ```
+
+## Using the GitLab Container Registry
+
+> **Notes:**
+- This feature requires GitLab 8.8 and GitLab Runner 1.2.
+- Starting from GitLab 8.12, if you have [2FA] enabled in your account, you need
+ to pass a [personal access token][pat] instead of your password in order to
+ login to GitLab's Container Registry.
+
+Once you've built a Docker image, you can push it up to the built-in
+[GitLab Container Registry](../../user/project/container_registry.md). For example,
+if you're using docker-in-docker on your runners, this is how your `.gitlab-ci.yml`
+could look like:
```yaml
build:
@@ -237,18 +298,42 @@ docker-in-docker on your runners, this is how your `.gitlab-ci.yml` could look:
- docker:dind
stage: build
script:
- - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.example.com
- - docker build -t registry.example.com/group/project:latest .
- - docker push registry.example.com/group/project:latest
+ - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.example.com
+ - docker build -t registry.example.com/group/project/image:latest .
+ - docker push registry.example.com/group/project/image:latest
+```
+
+You have to use the special `gitlab-ci-token` user created for you in order to
+push to the Registry connected to your project. Its password is provided in the
+`$CI_JOB_TOKEN` variable. This allows you to automate building and deployment
+of your Docker images.
+
+You can also make use of [other variables](../variables/README.md) to avoid hardcoding:
+
+```yaml
+services:
+ - docker:dind
+
+variables:
+ IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
+
+before_script:
+ - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
+
+build:
+ stage: build
+ script:
+ - docker build -t $IMAGE_TAG .
+ - docker push $IMAGE_TAG
```
-You have to use the credentials of the special `gitlab-ci-token` user with its
-password stored in `$CI_BUILD_TOKEN` in order to push to the Registry connected
-to your project. This allows you to automate building and deployment of your
-Docker images.
+Here, `$CI_REGISTRY_IMAGE` would be resolved to the address of the registry tied
+to this project, and `$CI_COMMIT_REF_NAME` would be resolved to the branch or
+tag name for this particular job. We also declare our own variable, `$IMAGE_TAG`,
+combining the two to save us some typing in the `script` section.
Here's a more elaborate example that splits up the tasks into 4 pipeline stages,
-including two tests that run in parallel. The build is stored in the container
+including two tests that run in parallel. The `build` is stored in the container
registry and used by subsequent stages, downloading the image
when needed. Changes to `master` also get tagged as `latest` and deployed using
an application-specific deploy script:
@@ -265,11 +350,11 @@ stages:
- deploy
variables:
- CONTAINER_TEST_IMAGE: registry.example.com/my-group/my-project:$CI_BUILD_REF_NAME
- CONTAINER_RELEASE_IMAGE: registry.example.com/my-group/my-project:latest
+ CONTAINER_TEST_IMAGE: registry.example.com/my-group/my-project/my-image:$CI_COMMIT_REF_NAME
+ CONTAINER_RELEASE_IMAGE: registry.example.com/my-group/my-project/my-image:latest
before_script:
- - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.example.com
+ - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.example.com
build:
stage: build
@@ -307,10 +392,22 @@ deploy:
```
Some things you should be aware of when using the Container Registry:
-* You must log in to the container registry before running commands. Putting this in `before_script` will run it before each build job.
-* Using `docker build --pull` makes sure that Docker fetches any changes to base images before building just in case your cache is stale. It takes slightly longer, but means you don’t get stuck without security patches to base images.
-* Doing an explicit `docker pull` before each `docker run` makes sure to fetch the latest image that was just built. This is especially important if you are using multiple runners that cache images locally. Using the git SHA in your image tag makes this less necessary since each build will be unique and you shouldn't ever have a stale image, but it's still possible if you re-build a given commit after a dependency has changed.
-* You don't want to build directly to `latest` in case there are multiple builds happening simultaneously.
+
+- You must log in to the container registry before running commands. Putting
+ this in `before_script` will run it before each job.
+- Using `docker build --pull` makes sure that Docker fetches any changes to base
+ images before building just in case your cache is stale. It takes slightly
+ longer, but means you don’t get stuck without security patches to base images.
+- Doing an explicit `docker pull` before each `docker run` makes sure to fetch
+ the latest image that was just built. This is especially important if you are
+ using multiple runners that cache images locally. Using the git SHA in your
+ image tag makes this less necessary since each job will be unique and you
+ shouldn't ever have a stale image, but it's still possible if you re-build a
+ given commit after a dependency has changed.
+- You don't want to build directly to `latest` in case there are multiple jobs
+ happening simultaneously.
[docker-in-docker]: https://blog.docker.com/2013/09/docker-can-now-run-within-docker/
[docker-cap]: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities
+[2fa]: ../../user/profile/account/two_factor_authentication.md
+[pat]: ../../user/profile/personal_access_tokens.md
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index 520c8b36a95..be4dea55c20 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -8,7 +8,7 @@ run applications in independent "containers" that are run within a single Linux
instance. [Docker Hub][hub] has a rich database of pre-built images that can be
used to test and build your applications.
-Docker, when used with GitLab CI, runs each build in a separate and isolated
+Docker, when used with GitLab CI, runs each job in a separate and isolated
container using the predefined image that is set up in
[`.gitlab-ci.yml`](../yaml/README.md).
@@ -37,20 +37,22 @@ The registered runner will use the `ruby:2.1` docker image and will run two
services, `postgres:latest` and `mysql:latest`, both of which will be
accessible during the build process.
-## What is image
+## What is an image
-The `image` keyword is the name of the docker image that is present in the
-local Docker Engine (list all images with `docker images`) or any image that
-can be found at [Docker Hub][hub]. For more information about images and Docker
-Hub please read the [Docker Fundamentals][] documentation.
+The `image` keyword is the name of the docker image the docker executor
+will run to perform the CI tasks.
-In short, with `image` we refer to the docker image, which will be used to
-create a container on which your build will run.
+By default the executor will only pull images from [Docker Hub][hub],
+but this can be configured in the `gitlab-runner/config.toml` by setting
+the [docker pull policy][] to allow using local images.
-## What is service
+For more information about images and Docker Hub please read
+the [Docker Fundamentals][] documentation.
+
+## What is a service
The `services` keyword defines just another docker image that is run during
-your build and is linked to the docker image that the `image` keyword defines.
+your job and is linked to the docker image that the `image` keyword defines.
This allows you to access the service image during build time.
The service image can run any application, but the most common use case is to
@@ -61,13 +63,13 @@ time the project is built.
You can see some widely used services examples in the relevant documentation of
[CI services examples](../services/README.md).
-### How is service linked to the build
+### How services are linked to the job
To better understand how the container linking works, read
[Linking containers together][linking-containers].
To summarize, if you add `mysql` as service to your application, the image will
-then be used to create a container that is linked to the build container.
+then be used to create a container that is linked to the job container.
The service container for MySQL will be accessible under the hostname `mysql`.
So, in order to access your database service you have to connect to the host
@@ -133,26 +135,63 @@ Look for the `[runners.docker]` section:
services = ["mysql:latest", "postgres:latest"]
```
-The image and services defined this way will be added to all builds run by
+The image and services defined this way will be added to all job run by
that runner.
## Define an image from a private Docker registry
-Starting with GitLab Runner 0.6.0, you are able to define images located to
-private registries that could also require authentication.
+> **Notes:**
+- This feature requires GitLab Runner **1.8** or higher
+- For GitLab Runner versions **>= 0.6, <1.8** there was a partial
+ support for using private registries, which required manual configuration
+ of credentials on runner's host. We recommend to upgrade your Runner to
+ at least version **1.8** if you want to use private registries.
+- If the repository is private you need to authenticate your GitLab Runner in the
+ registry. Learn more about how [GitLab Runner works in this case][runner-priv-reg].
-All you have to do is be explicit on the image definition in `.gitlab-ci.yml`.
+As an example, let's assume that you want to use the `registry.example.com/private/image:latest`
+image which is private and requires you to login into a private container registry.
+To configure access for `registry.example.com`, follow these steps:
-```yaml
-image: my.registry.tld:5000/namepace/image:tag
-```
+1. Do a `docker login` on your computer:
+
+ ```bash
+ docker login registry.example.com --username my_username --password my_password
+ ```
+
+1. Copy the content of `~/.docker/config.json`
+1. Create a [secret variable] `DOCKER_AUTH_CONFIG` with the content of the
+ Docker configuration file as the value:
+
+ ```json
+ {
+ "auths": {
+ "registry.example.com": {
+ "auth": "bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ="
+ }
+ }
+ }
+ ```
+
+1. Do a `docker logout` on your computer if you don't need access to the
+ registry from it:
+
+ ```bash
+ docker logout registry.example.com
+ ```
+
+1. You can now use any private image from `registry.example.com` defined in
+ `image` and/or `services` in your [`.gitlab-ci.yml` file][yaml-priv-reg]:
-In the example above, GitLab Runner will look at `my.registry.tld:5000` for the
-image `namespace/image:tag`.
+ ```yaml
+ image: my.registry.tld:5000/namespace/image:tag
+ ```
-If the repository is private you need to authenticate your GitLab Runner in the
-registry. Learn how to do that on
-[GitLab Runner's documentation][runner-priv-reg].
+ In the example above, GitLab Runner will look at `my.registry.tld:5000` for the
+ image `namespace/image:tag`.
+
+You can add configuration for as many registries as you want, adding more
+registries to the `"auths"` hash as described above.
## Accessing the services
@@ -167,14 +206,30 @@ services:
- tutum/wordpress:latest
```
-When the build is run, `tutum/wordpress` will be started and you will have
-access to it from your build container under the hostname `tutum__wordpress`.
+When the job is run, `tutum/wordpress` will be started and you will have
+access to it from your build container under the hostnames `tutum-wordpress`
+(requires GitLab Runner v1.1.0 or newer) and `tutum__wordpress`.
+
+When using a private registry, the image name also includes a hostname and port
+of the registry.
+
+```yaml
+services:
+- docker.example.com:5000/wordpress:latest
+```
+
+The service hostname will also include the registry hostname. Service will be
+available under hostnames `docker.example.com-wordpress` (requires GitLab Runner v1.1.0 or newer)
+and `docker.example.com__wordpress`.
+
+*Note: hostname with underscores is not RFC valid and may cause problems in 3rd party applications.*
-The alias hostname for the service is made from the image name following these
+The alias hostnames for the service are made from the image name following these
rules:
1. Everything after `:` is stripped
-2. Slash (`/`) is replaced with double underscores (`__`)
+2. Slash (`/`) is replaced with double underscores (`__`) - primary alias
+3. Slash (`/`) is replaced with dash (`-`) - secondary alias, requires GitLab Runner v1.1.0 or newer
## Configuring services
@@ -202,21 +257,21 @@ See the specific documentation for
## How Docker integration works
-Below is a high level overview of the steps performed by docker during build
+Below is a high level overview of the steps performed by docker during job
time.
1. Create any service container: `mysql`, `postgresql`, `mongodb`, `redis`.
1. Create cache container to store all volumes as defined in `config.toml` and
`Dockerfile` of build image (`ruby:2.1` as in above example).
1. Create build container and link any service container to build container.
-1. Start build container and send build script to the container.
-1. Run build script.
+1. Start build container and send job script to the container.
+1. Run job script.
1. Checkout code in: `/builds/group-name/project-name/`.
1. Run any step defined in `.gitlab-ci.yml`.
1. Check exit status of build script.
1. Remove build container and all created service containers.
-## How to debug a build locally
+## How to debug a job locally
*Note: The following commands are run without root privileges. You should be
able to run docker with your regular user account.*
@@ -271,9 +326,11 @@ containers as well as all volumes (`-v`) that were created with the container
creation.
[Docker Fundamentals]: https://docs.docker.com/engine/understanding-docker/
+[docker pull policy]: https://docs.gitlab.com/runner/executors/docker.html#how-pull-policies-work
[hub]: https://hub.docker.com/
[linking-containers]: https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/
[tutum/wordpress]: https://hub.docker.com/r/tutum/wordpress/
[postgres-hub]: https://hub.docker.com/r/_/postgres/
[mysql-hub]: https://hub.docker.com/r/_/mysql/
-[runner-priv-reg]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/configuration/advanced-configuration.md#using-a-private-docker-registry
+[runner-priv-reg]: http://docs.gitlab.com/runner/configuration/advanced-configuration.html#using-a-private-container-registry
+[secret variable]: ../variables/README.md#secret-variables
diff --git a/doc/ci/enable_or_disable_ci.md b/doc/ci/enable_or_disable_ci.md
index c10f82054e2..796a025b951 100644
--- a/doc/ci/enable_or_disable_ci.md
+++ b/doc/ci/enable_or_disable_ci.md
@@ -11,10 +11,10 @@ API.
---
-As of GitLab 8.2, GitLab CI is mainly exposed via the `/builds` page of a
-project. Disabling GitLab CI in a project does not delete any previous builds.
-In fact, the `/builds` page can still be accessed, although it's hidden from
-the left sidebar menu.
+GitLab CI is exposed via the `/pipelines` and `/builds` pages of a project.
+Disabling GitLab CI in a project does not delete any previous jobs.
+In fact, the `/pipelines` and `/builds` pages can still be accessed, although
+it's hidden from the left sidebar menu.
GitLab CI is enabled by default on new installations and can be disabled either
individually under each project's settings, or site-wide by modifying the
@@ -23,12 +23,12 @@ respectively.
### Per-project user setting
-The setting to enable or disable GitLab CI can be found with the name **Builds**
-under the **Features** area of a project's settings along with **Issues**,
-**Merge Requests**, **Wiki** and **Snippets**. Select or deselect the checkbox
-and hit **Save** for the settings to take effect.
+The setting to enable or disable GitLab CI can be found with the name **Pipelines**
+under the **Sharing & Permissions** area of a project's settings along with
+**Merge Requests**. Choose one of **Disabled**, **Only team members** and
+**Everyone with access** and hit **Save changes** for the settings to take effect.
-![Features settings](img/features_settings.png)
+![Sharing & Permissions settings](img/permissions_settings.png)
---
diff --git a/doc/ci/environments.md b/doc/ci/environments.md
index e070302fb82..3393030210e 100644
--- a/doc/ci/environments.md
+++ b/doc/ci/environments.md
@@ -1,71 +1,674 @@
# Introduction to environments and deployments
->**Note:**
-Introduced in GitLab 8.9.
+> Introduced in GitLab 8.9.
-## Environments
+During the development of software, there can be many stages until it's ready
+for public consumption. You sure want to first test your code and then deploy it
+in a testing or staging environment before you release it to the public. That
+way you can prevent bugs not only in your software, but in the deployment
+process as well.
-Environments are places where code gets deployed, such as staging or production.
-CI/CD [Pipelines] usually have one or more [jobs] that deploy to an environment.
-Defining environments in a project's `.gitlab-ci.yml` lets developers track
-[deployments] to these environments.
+GitLab CI is capable of not only testing or building your projects, but also
+deploying them in your infrastructure, with the added benefit of giving you a
+way to track your deployments. In other words, you can always know what is
+currently being deployed or has been deployed on your servers.
-## Deployments
+## Overview
-Deployments are created when [jobs] deploy versions of code to [environments].
+With environments, you can control the Continuous Deployment of your software
+all within GitLab. All you need to do is define them in your project's
+[`.gitlab-ci.yml`][yaml] as we will explore below. GitLab provides a full
+history of your deployments per every environment.
-### Checkout deployments locally
+Environments are like tags for your CI jobs, describing where code gets deployed.
+Deployments are created when [jobs] deploy versions of code to environments,
+so every environment can have one or more deployments. GitLab keeps track of
+your deployments, so you always know what is currently being deployed on your
+servers. If you have a deployment service such as [Kubernetes][kubernetes-service]
+enabled for your project, you can use it to assist with your deployments, and
+can even access a web terminal for your environment from within GitLab!
-Since 8.13, a reference in the git repository is saved for each deployment. So
-knowing what the state is of your current environments is only a `git fetch`
-away.
+To better understand how environments and deployments work, let's consider an
+example. We assume that you have already created a project in GitLab and set up
+a Runner. The example will cover the following:
-In your git config, append the `[remote "<your-remote>"]` block with an extra
-fetch line:
+- We are developing an application
+- We want to run tests and build our app on all branches
+- Our default branch is `master`
+- We deploy the app only when a pipeline on `master` branch is run
+
+Let's see how it all ties together.
+
+## Defining environments
+Let's consider the following `.gitlab-ci.yml` example:
+
+```yaml
+stages:
+ - test
+ - build
+ - deploy
+
+test:
+ stage: test
+ script: echo "Running tests"
+
+build:
+ stage: build
+ script: echo "Building the app"
+
+deploy_staging:
+ stage: deploy
+ script:
+ - echo "Deploy to staging server"
+ environment:
+ name: staging
+ url: https://staging.example.com
+ only:
+ - master
```
-fetch = +refs/environments/*:refs/remotes/origin/environments/*
+
+We have defined 3 [stages](yaml/README.md#stages):
+
+- test
+- build
+- deploy
+
+The jobs assigned to these stages will run in this order. If a job fails, then
+the jobs that are assigned to the next stage won't run, rendering the pipeline
+as failed. In our case, the `test` job will run first, then the `build` and
+lastly the `deploy_staging`. With this, we ensure that first the tests pass,
+then our app is able to be built successfully, and lastly we deploy to the
+staging server.
+
+The `environment` keyword is just a hint for GitLab that this job actually
+deploys to this environment's `name`. It can also have a `url` which, as we
+will later see, is exposed in various places within GitLab. Each time a job that
+has an environment specified and succeeds, a deployment is recorded, remembering
+the Git SHA and environment name.
+
+>**Note:**
+Starting with GitLab 8.15, the environment name is exposed to the Runner in
+two forms: `$CI_ENVIRONMENT_NAME`, and `$CI_ENVIRONMENT_SLUG`. The first is
+the name given in `.gitlab-ci.yml` (with any variables expanded), while the
+second is a "cleaned-up" version of the name, suitable for use in URLs, DNS,
+etc.
+
+>**Note:**
+Starting with GitLab 9.3, the environment URL is exposed to the Runner via
+`$CI_ENVIRONMENT_URL`. The URL would be expanded from `.gitlab-ci.yml`, or if
+the URL was not defined there, the external URL from the environment would be
+used.
+
+To sum up, with the above `.gitlab-ci.yml` we have achieved that:
+
+- All branches will run the `test` and `build` jobs.
+- The `deploy_staging` job will run [only](yaml/README.md#only) on the `master`
+ branch which means all merge requests that are created from branches don't
+ get to deploy to the staging server
+- When a merge request is merged, all jobs will run and the `deploy_staging`
+ in particular will deploy our code to a staging server while the deployment
+ will be recorded in an environment named `staging`.
+
+Let's now see how that information is exposed within GitLab.
+
+## Viewing the current status of an environment
+
+The environment list under your project's **Pipelines ➔ Environments**, is
+where you can find information of the last deployment status of an environment.
+
+Here's how the Environments page looks so far.
+
+![Staging environment view](img/environments_available_staging.png)
+
+There's a bunch of information there, specifically you can see:
+
+- The environment's name with a link to its deployments
+- The last deployment ID number and who performed it
+- The job ID of the last deployment with its respective job name
+- The commit information of the last deployment such as who committed, to what
+ branch and the Git SHA of the commit
+- The exact time the last deployment was performed
+- A button that takes you to the URL that you have defined under the
+ `environment` keyword in `.gitlab-ci.yml`
+- A button that re-deploys the latest deployment, meaning it runs the job
+ defined by the environment name for that specific commit
+
+>**Notes:**
+- While you can create environments manually in the web interface, we recommend
+ that you define your environments in `.gitlab-ci.yml` first. They will
+ be automatically created for you after the first deploy.
+- The environments page can only be viewed by Reporters and above. For more
+ information on the permissions, see the [permissions documentation][permissions].
+- Only deploys that happen after your `.gitlab-ci.yml` is properly configured
+ will show up in the "Environment" and "Last deployment" lists.
+
+The information shown in the Environments page is limited to the latest
+deployments, but as you may have guessed an environment can have multiple
+deployments.
+
+## Viewing the deployment history of an environment
+
+GitLab keeps track of your deployments, so you always know what is currently
+being deployed on your servers. That way you can have the full history of your
+deployments per every environment right in your browser. Clicking on an
+environment will show the history of its deployments. Assuming you have deployed
+multiple times already, here's how a specific environment's page looks like.
+
+![Deployments](img/deployments_view.png)
+
+We can see the same information as when in the Environments page, but this time
+all deployments are shown. As you may have noticed, apart from the **Re-deploy**
+button there are now **Rollback** buttons for each deployment. Let's see how
+that works.
+
+## Rolling back changes
+
+You can't control everything, so sometimes things go wrong. When that unfortunate
+time comes GitLab has you covered. Simply by clicking the **Rollback** button
+that can be found in the deployments page
+(**Pipelines ➔ Environments ➔ `environment name`**) you can relaunch the
+job with the commit associated with it.
+
+>**Note:**
+Bear in mind that your mileage will vary and it's entirely up to how you define
+the deployment process in the job's `script` whether the rollback succeeds or not.
+GitLab CI is just following orders.
+
+Thankfully that was the staging server that we had to rollback, and since we
+learn from our mistakes, we decided to not make the same again when we deploy
+to the production server. Enter manual actions for deployments.
+
+## Manually deploying to environments
+
+Turning a job from running automatically to a manual action is as simple as
+adding `when: manual` to it. To expand on our previous example, let's add
+another job that this time deploys our app to a production server and is
+tracked by a `production` environment. The `.gitlab-ci.yml` looks like this
+so far:
+
+```yaml
+stages:
+ - test
+ - build
+ - deploy
+
+test:
+ stage: test
+ script: echo "Running tests"
+
+build:
+ stage: build
+ script: echo "Building the app"
+
+deploy_staging:
+ stage: deploy
+ script:
+ - echo "Deploy to staging server"
+ environment:
+ name: staging
+ url: https://staging.example.com
+ only:
+ - master
+
+deploy_prod:
+ stage: deploy
+ script:
+ - echo "Deploy to production server"
+ environment:
+ name: production
+ url: https://example.com
+ when: manual
+ only:
+ - master
```
-## Defining environments
+The `when: manual` action exposes a play button in GitLab's UI and the
+`deploy_prod` job will only be triggered if and when we click that play button.
+You can find it in the pipeline, job, environment, and deployment views.
+
+| Pipelines | Single pipeline | Environments | Deployments | jobs |
+| --------- | ----------------| ------------ | ----------- | -------|
+| ![Pipelines manual action](img/environments_manual_action_pipelines.png) | ![Pipelines manual action](img/environments_manual_action_single_pipeline.png) | ![Environments manual action](img/environments_manual_action_environments.png) | ![Deployments manual action](img/environments_manual_action_deployments.png) | ![Builds manual action](img/environments_manual_action_builds.png) |
+
+Clicking on the play button in either of these places will trigger the
+`deploy_prod` job, and the deployment will be recorded under a new
+environment named `production`.
+
+>**Note:**
+Remember that if your environment's name is `production` (all lowercase), then
+it will get recorded in [Cycle Analytics](../user/project/cycle_analytics.md).
+Double the benefit!
+
+## Web terminals
+
+>**Note:**
+Web terminals were added in GitLab 8.15 and are only available to project
+masters and owners.
+
+If you deploy to your environments with the help of a deployment service (e.g.,
+the [Kubernetes service][kubernetes-service], GitLab can open
+a terminal session to your environment! This is a very powerful feature that
+allows you to debug issues without leaving the comfort of your web browser. To
+enable it, just follow the instructions given in the service documentation.
+
+Once enabled, your environments will gain a "terminal" button:
+
+![Terminal button on environment index](img/environments_terminal_button_on_index.png)
+
+You can also access the terminal button from the page for a specific environment:
-You can create and delete environments manually in the web interface, but we
-recommend that you define your environments in `.gitlab-ci.yml` first, which
-will automatically create environments for you after the first deploy.
+![Terminal button for an environment](img/environments_terminal_button_on_show.png)
-The `environment` is just a hint for GitLab that this job actually deploys to
-this environment. Each time the job succeeds, a deployment is recorded,
-remembering the git SHA and environment.
+Wherever you find it, clicking the button will take you to a separate page to
+establish the terminal session:
-Add something like this to your `.gitlab-ci.yml`:
+![Terminal page](img/environments_terminal_page.png)
+
+This works just like any other terminal - you'll be in the container created
+by your deployment, so you can run shell commands and get responses in real
+time, check the logs, try out configuration or code tweaks, etc. You can open
+multiple terminals to the same environment - they each get their own shell
+session - and even a multiplexer like `screen` or `tmux`!
+
+>**Note:**
+Container-based deployments often lack basic tools (like an editor), and may
+be stopped or restarted at any time. If this happens, you will lose all your
+changes! Treat this as a debugging tool, not a comprehensive online IDE. You
+can use [Koding](../administration/integration/koding.md) for online
+development.
+
+---
+
+While this is fine for deploying to some stable environments like staging or
+production, what happens for branches? So far we haven't defined anything
+regarding deployments for branches other than `master`. Dynamic environments
+will help us achieve that.
+
+## Dynamic environments
+
+As the name suggests, it is possible to create environments on the fly by just
+declaring their names dynamically in `.gitlab-ci.yml`. Dynamic environments is
+the basis of [Review apps](review_apps/index.md).
+
+GitLab Runner exposes various [environment variables][variables] when a job runs,
+and as such, you can use them as environment names. Let's add another job in
+our example which will deploy to all branches except `master`:
+
+```yaml
+deploy_review:
+ stage: deploy
+ script:
+ - echo "Deploy a review app"
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ url: https://$CI_ENVIRONMENT_SLUG.example.com
+ only:
+ - branches
+ except:
+ - master
```
-production:
+
+Let's break it down in pieces. The job's name is `deploy_review` and it runs
+on the `deploy` stage. The `script` at this point is fictional, you'd have to
+use your own based on your deployment. Then, we set the `environment` with the
+`environment:name` being `review/$CI_COMMIT_REF_NAME`. Now that's an interesting
+one. Since the [environment name][env-name] can contain slashes (`/`), we can
+use this pattern to distinguish between dynamic environments and the regular
+ones.
+
+So, the first part is `review`, followed by a `/` and then `$CI_COMMIT_REF_NAME`
+which takes the value of the branch name. Since `$CI_COMMIT_REF_NAME` itself may
+also contain `/`, or other characters that would be invalid in a domain name or
+URL, we use `$CI_ENVIRONMENT_SLUG` in the `environment:url` so that the
+environment can get a specific and distinct URL for each branch. In this case,
+given a `$CI_COMMIT_REF_NAME` of `100-Do-The-Thing`, the URL will be something
+like `https://100-do-the-4f99a2.example.com`. Again, the way you set up
+the web server to serve these requests is based on your setup.
+
+You could also use `$CI_COMMIT_REF_SLUG` in `environment:url`, e.g.:
+`https://$CI_COMMIT_REF_SLUG.example.com`. We use `$CI_ENVIRONMENT_SLUG`
+here because it is guaranteed to be unique, but if you're using a workflow like
+[GitLab Flow][gitlab-flow], collisions are very unlikely, and you may prefer
+environment names to be more closely based on the branch name - the example
+above would give you an URL like `https://100-do-the-thing.example.com`
+
+Last but not least, we tell the job to run [`only`][only] on branches
+[`except`][only] master.
+
+>**Note:**
+You are not bound to use the same prefix or only slashes in the dynamic
+environments' names (`/`), but as we will see later, this will enable the
+[grouping similar environments](#grouping-similar-environments) feature.
+
+The whole `.gitlab-ci.yml` looks like this so far:
+
+```yaml
+stages:
+ - test
+ - build
+ - deploy
+
+test:
+ stage: test
+ script: echo "Running tests"
+
+build:
+ stage: build
+ script: echo "Building the app"
+
+deploy_review:
+ stage: deploy
+ script:
+ - echo "Deploy a review app"
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ url: https://$CI_ENVIRONMENT_SLUG.example.com
+ only:
+ - branches
+ except:
+ - master
+
+deploy_staging:
+ stage: deploy
+ script:
+ - echo "Deploy to staging server"
+ environment:
+ name: staging
+ url: https://staging.example.com
+ only:
+ - master
+
+deploy_prod:
stage: deploy
- script: dpl...
- environment: production
+ script:
+ - echo "Deploy to production server"
+ environment:
+ name: production
+ url: https://example.com
+ when: manual
+ only:
+ - master
```
-See full [documentation](yaml/README.md#environment).
+A more realistic example would include copying files to a location where a
+webserver (NGINX) could then read and serve. The example below will copy the
+`public` directory to `/srv/nginx/$CI_COMMIT_REF_SLUG/public`:
-## Seeing environment status
+```yaml
+review_app:
+ stage: deploy
+ script:
+ - rsync -av --delete public /srv/nginx/$CI_COMMIT_REF_SLUG
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ url: https://$CI_COMMIT_REF_SLUG.example.com
+```
-You can find the environment list under **Pipelines > Environments** for your
-project. You'll see the git SHA and date of the last deployment to each
-environment defined.
+It is assumed that the user has already setup NGINX and GitLab Runner in the
+server this job will run on.
>**Note:**
-Only deploys that happen after your `.gitlab-ci.yml` is properly configured will
-show up in the environments and deployments lists.
+Be sure to check out the [limitations](#limitations) section for some edge
+cases regarding naming of your branches and Review Apps.
+
+---
+
+The development workflow would now be:
+
+- Developer creates a branch locally
+- Developer makes changes, commits and pushes the branch to GitLab
+- Developer creates a merge request
+
+Behind the scenes:
+
+- GitLab Runner picks up the changes and starts running the jobs
+- The jobs run sequentially as defined in `stages`
+ - First, the tests pass
+ - Then, the job begins and successfully also passes
+ - Lastly, the app is deployed to an environment with a name specific to the
+ branch
+
+So now, every branch gets its own environment and is deployed to its own place
+with the added benefit of having a [history of deployments](#viewing-the-deployment-history-of-an-environment)
+and also being able to [rollback changes](#rolling-back-changes) if needed.
+Let's briefly see where URL that's defined in the environments is exposed.
+
+## Making use of the environment URL
+
+The environment URL is exposed in a few places within GitLab.
+
+| In a merge request widget as a link | In the Environments view as a button | In the Deployments view as a button |
+| -------------------- | ------------ | ----------- |
+| ![Environment URL in merge request](img/environments_mr_review_app.png) | ![Environment URL in environments](img/environments_link_url.png) | ![Environment URL in deployments](img/environments_link_url_deployments.png) |
+
+If a merge request is eventually merged to the default branch (in our case
+`master`) and that branch also deploys to an environment (in our case `staging`
+and/or `production`) you can see this information in the merge request itself.
+
+![Environment URLs in merge request](img/environments_link_url_mr.png)
+
+### <a name="route-map"></a>Go directly from source files to public pages on the environment
+
+
+> Introduced in GitLab 8.17.
+
+To go one step further, we can specify a Route Map to get GitLab to show us "View on [environment URL]" buttons to go directly from a file to that file's representation on the deployed website. It will be exposed in a few places:
+
+| In the diff for a merge request, comparison or commit | In the file view |
+| ------ | ------ |
+| !["View on env" button in merge request diff](img/view_on_env_mr.png) | !["View on env" button in file view](img/view_on_env_blob.png) |
+
+To get this to work, you need to tell GitLab how the paths of files in your repository map to paths of pages on your website, using a Route Map.
+
+A Route Map is a file inside the repository at `.gitlab/route-map.yml`, which contains a YAML array that maps `source` paths (in the repository) to `public` paths (on the website).
+
+This is an example of a route map for [Middleman](https://middlemanapp.com) static websites like [http://about.gitlab.com](https://gitlab.com/gitlab-com/www-gitlab-com):
+
+```yaml
+# Team data
+- source: 'data/team.yml' # data/team.yml
+ public: 'team/' # team/
+
+# Blogposts
+- source: /source\/posts\/([0-9]{4})-([0-9]{2})-([0-9]{2})-(.+?)\..*/ # source/posts/2017-01-30-around-the-world-in-6-releases.html.md.erb
+ public: '\1/\2/\3/\4/' # 2017/01/30/around-the-world-in-6-releases/
+
+# HTML files
+- source: /source\/(.+?\.html).*/ # source/index.html.haml
+ public: '\1' # index.html
+
+# Other files
+- source: /source\/(.*)/ # source/images/blogimages/around-the-world-in-6-releases-cover.png
+ public: '\1' # images/blogimages/around-the-world-in-6-releases-cover.png
+```
+
+Mappings are defined as entries in the root YAML array, and are identified by a `-` prefix. Within an entry, we have a hash map with two keys:
+
+- `source`
+ - a string, starting and ending with `'`, for an exact match
+ - a regular expression, starting and ending with `/`, for a pattern match
+ - The regular expression needs to match the entire source path - `^` and `$` anchors are implied.
+ - Can include capture groups denoted by `()` that can be referred to in the `public` path.
+ - Slashes (`/`) can, but don't have to, be escaped as `\/`.
+ - Literal periods (`.`) should be escaped as `\.`.
+- `public`
+ - a string, starting and ending with `'`.
+ - Can include `\N` expressions to refer to capture groups in the `source` regular expression in order of their occurence, starting with `\1`.
+
+The public path for a source path is determined by finding the first `source` expression that matches it, and returning the corresponding `public` path, replacing the `\N` expressions with the values of the `()` capture groups if appropriate.
+
+In the example above, the fact that mappings are evaluated in order of their definition is used to ensure that `source/index.html.haml` will match `/source\/(.+?\.html).*/` instead of `/source\/(.*)/`, and will result in a public path of `index.html`, instead of `index.html.haml`.
+
+---
+
+We now have a full development cycle, where our app is tested, built, deployed
+as a Review app, deployed to a staging server once the merge request is merged,
+and finally manually deployed to the production server. What we just described
+is a single workflow, but imagine tens of developers working on a project
+at the same time. They each push to their branches, and dynamic environments are
+created all the time. In that case, we probably need to do some clean up. Read
+next how environments can be stopped.
+
+## Stopping an environment
+
+By stopping an environment, you are effectively terminating its recording of the
+deployments that happen in it.
+
+A branch is associated with an environment when the CI pipeline that is created
+for this branch, was recently deployed to this environment. You can think of
+the CI pipeline as the glue between the branch and the environment:
+`branch ➔ CI pipeline ➔ environment`.
-## Seeing deployment history
+There is a special case where environments can be manually stopped. That can
+happen if you provide another job for that matter. The syntax is a little
+tricky since a job calls another job to do the job.
-Clicking on an environment will show the history of deployments.
+Consider the following example where the `deploy_review` calls the `stop_review`
+to clean up and stop the environment:
+
+```yaml
+deploy_review:
+ stage: deploy
+ script:
+ - echo "Deploy a review app"
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ url: https://$CI_ENVIRONMENT_SLUG.example.com
+ on_stop: stop_review
+ only:
+ - branches
+ except:
+ - master
+
+stop_review:
+ stage: deploy
+ variables:
+ GIT_STRATEGY: none
+ script:
+ - echo "Remove review app"
+ when: manual
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ action: stop
+```
+
+Setting the [`GIT_STRATEGY`][git-strategy] to `none` is necessary on the
+`stop_review` job so that the [GitLab Runner] won't try to checkout the code
+after the branch is deleted.
>**Note:**
-Only deploys that happen after your `.gitlab-ci.yml` is properly configured will
-show up in the environments and deployments lists.
+Starting with GitLab 8.14, dynamic environments will be stopped automatically
+when their associated branch is deleted.
+
+When you have an environment that has a stop action defined (typically when
+the environment describes a review app), GitLab will automatically trigger a
+stop action when the associated branch is deleted. The `stop_review` job must
+be in the same `stage` as the `deploy_review` one in order for the environment
+to automatically stop.
+
+You can read more in the [`.gitlab-ci.yml` reference][onstop].
+
+## Grouping similar environments
+
+> [Introduced][ce-7015] in GitLab 8.14.
+
+As we've seen in the [dynamic environments](#dynamic-environments), you can
+prepend their name with a word, then followed by a `/` and finally the branch
+name which is automatically defined by the `CI_COMMIT_REF_NAME` variable.
+
+In short, environments that are named like `type/foo` are presented under a
+group named `type`.
+
+In our minimal example, we name the environments `review/$CI_COMMIT_REF_NAME`
+where `$CI_COMMIT_REF_NAME` is the branch name:
+
+```yaml
+deploy_review:
+ stage: deploy
+ script:
+ - echo "Deploy a review app"
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+```
+
+In that case, if you visit the Environments page, and provided the branches
+exist, you should see something like:
+
+![Environment groups](img/environments_dynamic_groups.png)
+
+## Monitoring environments
+
+>**Notes:**
+>
+- For the monitor dashboard to appear, you need to:
+ - Have enabled the [Kubernetes integration][kube]
+ - Have your app deployed on Kubernetes
+ - Have enabled the [Prometheus integration][prom]
+- With GitLab 9.2, all deployments to an environment are shown directly on the
+ monitoring dashboard
+
+If your application is deployed on Kubernetes and you have enabled Prometheus
+collecting metrics, you can monitor the performance behavior of your app
+through the environments.
+
+Once configured, GitLab will attempt to retrieve performance metrics for any
+environment which has had a successful deployment. If monitoring data was
+successfully retrieved, a Monitoring button will appear on the environment's
+detail page.
+
+![Environment Detail with Metrics](img/prometheus_environment_detail_with_metrics.png)
+
+Clicking on the Monitoring button will display a new page, showing up to the last
+8 hours of performance data. It may take a minute or two for data to appear
+after initial deployment.
+
+All deployments to an environment are shown directly on the monitoring dashboard
+which allows easy correlation between any changes in performance and a new
+version of the app, all without leaving GitLab.
+
+![Monitoring dashboard](img/environments_monitoring.png)
+
+## Checkout deployments locally
+
+Since 8.13, a reference in the git repository is saved for each deployment, so
+knowing the state of your current environments is only a `git fetch` away.
+
+In your git config, append the `[remote "<your-remote>"]` block with an extra
+fetch line:
+
+```
+fetch = +refs/environments/*:refs/remotes/origin/environments/*
+```
+
+## Limitations
+
+1. You are limited to use only the [CI predefined variables][variables] in the
+ `environment: name`. If you try to re-use variables defined inside `script`
+ as part of the environment name, it will not work.
+
+## Further reading
+
+Below are some links you may find interesting:
+
+- [The `.gitlab-ci.yml` definition of environments](yaml/README.md#environment)
+- [A blog post on Deployments & Environments](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/)
+- [Review Apps - Use dynamic environments to deploy your code for every branch](review_apps/index.md)
[Pipelines]: pipelines.md
[jobs]: yaml/README.md#jobs
+[yaml]: yaml/README.md
+[kubernetes-service]: ../user/project/integrations/kubernetes.md
[environments]: #environments
[deployments]: #deployments
+[permissions]: ../user/permissions.md
+[variables]: variables/README.md
+[env-name]: yaml/README.md#environment-name
+[only]: yaml/README.md#only-and-except
+[onstop]: yaml/README.md#environment-on_stop
+[ce-7015]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7015
+[gitlab-flow]: ../workflow/gitlab_flow.md
+[gitlab runner]: https://docs.gitlab.com/runner/
+[git-strategy]: yaml/README.md#git-strategy
+[kube]: ../user/project/integrations/kubernetes.md
+[prom]: ../user/project/integrations/prometheus.md
diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md
index 40f0165deef..2458cb959ab 100644
--- a/doc/ci/examples/README.md
+++ b/doc/ci/examples/README.md
@@ -1,4 +1,4 @@
-# CI Examples
+# GitLab CI Examples
A collection of `.gitlab-ci.yml` files is maintained at the [GitLab CI Yml project][gitlab-ci-templates].
If your favorite programming language or framework are missing we would love your help by sending a merge request
@@ -6,14 +6,74 @@ with a `.gitlab-ci.yml`.
Apart from those, here is an collection of tutorials and guides on setting up your CI pipeline:
+## Languages, frameworks, OSs
+
+### PHP
+
- [Testing a PHP application](php.md)
+- [Run PHP Composer & NPM scripts then deploy them to a staging server](deployment/composer-npm-deploy.md)
+
+### Ruby
+
- [Test and deploy a Ruby application to Heroku](test-and-deploy-ruby-application-to-heroku.md)
+
+### Python
+
- [Test and deploy a Python application to Heroku](test-and-deploy-python-application-to-heroku.md)
-- [Test a Clojure application](test-clojure-application.md)
+
+### Java
+
+- **Articles:**
+ - [Continuous Delivery of a Spring Boot application with GitLab CI and Kubernetes](https://about.gitlab.com/2016/12/14/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/)
+
+### Scala
+
- [Test a Scala application](test-scala-application.md)
+
+### Clojure
+
+- [Test a Clojure application](test-clojure-application.md)
+
+### Elixir
+
+- [Test a Phoenix application](test-phoenix-application.md)
+- **Articles:**
+ - [Building an Elixir Release into a Docker image using GitLab CI](https://about.gitlab.com/2016/08/11/building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1/)
+
+### iOS
+
+- **Articles:**
+ - [Setting up GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/)
+
+### Android
+
+- **Articles:**
+ - [Setting up GitLab CI for Android projects](https://about.gitlab.com/2016/11/30/setting-up-gitlab-ci-for-android-projects/)
+
+### Other
+
- [Using `dpl` as deployment tool](deployment/README.md)
-- [Blog post about using GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/)
- [Repositories with examples for various languages](https://gitlab.com/groups/gitlab-examples)
- [The .gitlab-ci.yml file for GitLab itself](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml)
+- [Analyze code quality with the Code Climate CLI](code_climate.md)
+- **Articles:**
+ - [Continuous Deployment with GitLab: how to build and deploy a Debian Package with GitLab CI](https://about.gitlab.com/2016/10/12/automated-debian-package-build-with-gitlab-ci/)
+
+## GitLab CI for GitLab Pages
+
+- [Example projects](https://gitlab.com/pages)
+- **Articles:**
+ - [Creating and Tweaking `.gitlab-ci.yml` for GitLab Pages](../../user/project/pages/getting_started_part_four.md)
+ - [SSGs Part 3: Build any SSG site with GitLab Pages](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/):
+ examples for Ruby-, NodeJS-, Python-, and GoLang-based SSGs
+ - [Building a new GitLab docs site with Nanoc, GitLab CI, and GitLab Pages](https://about.gitlab.com/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/)
+ - [Publish code coverage reports with GitLab Pages](https://about.gitlab.com/2016/11/03/publish-code-coverage-report-with-gitlab-pages/)
+
+See the topic [GitLab Pages](../../user/project/pages/index.md) for a complete overview.
+
+## More
+
+Contributions are very much welcomed! You can help your favorite programming
+language and GitLab by sending a merge request with a guide for that language.
[gitlab-ci-templates]: https://gitlab.com/gitlab-org/gitlab-ci-yml
diff --git a/doc/ci/examples/code_climate.md b/doc/ci/examples/code_climate.md
new file mode 100644
index 00000000000..5659a8c2a2a
--- /dev/null
+++ b/doc/ci/examples/code_climate.md
@@ -0,0 +1,34 @@
+# Analyze project code quality with Code Climate CLI
+
+This example shows how to run [Code Climate CLI][cli] on your code by using
+GitLab CI and Docker.
+
+First, you need GitLab Runner with [docker-in-docker executor][dind].
+
+Once you set up the Runner, add a new job to `.gitlab-ci.yml`, called `codeclimate`:
+
+```yaml
+codeclimate:
+ image: docker:latest
+ variables:
+ DOCKER_DRIVER: overlay
+ services:
+ - docker:dind
+ script:
+ - docker pull codeclimate/codeclimate
+ - docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate init
+ - docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate analyze -f json > codeclimate.json
+ artifacts:
+ paths: [codeclimate.json]
+```
+
+This will create a `codeclimate` job in your CI pipeline and will allow you to
+download and analyze the report artifact in JSON format.
+
+For GitLab [Enterprise Edition Starter][ee] users, this information can be automatically
+extracted and shown right in the merge request widget. [Learn more on code quality
+diffs in merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality_diff.html).
+
+[cli]: https://github.com/codeclimate/codeclimate
+[dind]: ../docker/using_docker_build.md#use-docker-in-docker-executor
+[ee]: https://about.gitlab.com/gitlab-ee/
diff --git a/doc/ci/examples/deployment/README.md b/doc/ci/examples/deployment/README.md
index 7d91ce6710f..e80e246c5dd 100644
--- a/doc/ci/examples/deployment/README.md
+++ b/doc/ci/examples/deployment/README.md
@@ -1,20 +1,30 @@
-## Using Dpl as deployment tool
-Dpl (dee-pee-ell) is a deploy tool made for continuous deployment that's developed and used by Travis CI, but can also be used with GitLab CI.
+# Using Dpl as deployment tool
-**We recommend to use Dpl, if you're deploying to any of these of these services: https://github.com/travis-ci/dpl#supported-providers**.
+[Dpl](https://github.com/travis-ci/dpl) (dee-pee-ell) is a deploy tool made for
+continuous deployment that's developed and used by Travis CI, but can also be
+used with GitLab CI.
-### Requirements
-To use Dpl you need at least Ruby 1.8.7 with ability to install gems.
+>**Note:**
+We recommend to use Dpl if you're deploying to any of these of these services:
+https://github.com/travis-ci/dpl#supported-providers.
+
+## Requirements
+
+To use Dpl you need at least Ruby 1.9.3 with ability to install gems.
+
+## Basic usage
+
+Dpl can be installed on any machine with:
-### Basic usage
-The Dpl can be installed on any machine with:
```
gem install dpl
```
-This allows you to test all commands from your shell, rather than having to test it on a CI server.
+This allows you to test all commands from your local terminal, rather than
+having to test it on a CI server.
If you don't have Ruby installed you can do it on Debian-compatible Linux with:
+
```
apt-get update
apt-get install ruby-dev
@@ -26,9 +36,10 @@ To use it simply define provider and any additional parameters required by the p
For example if you want to use it to deploy your application to heroku, you need to specify `heroku` as provider, specify `api-key` and `app`.
There's more and all possible parameters can be found here: https://github.com/travis-ci/dpl#heroku
-```
+```yaml
staging:
- type: deploy
+ stage: deploy
+ script:
- gem install dpl
- dpl --provider=heroku --app=my-app-staging --api-key=$HEROKU_STAGING_API_KEY
```
@@ -37,14 +48,17 @@ In the above example we use Dpl to deploy `my-app-staging` to Heroku server with
To use different provider take a look at long list of [Supported Providers](https://github.com/travis-ci/dpl#supported-providers).
-### Using Dpl with Docker
+## Using Dpl with Docker
+
When you use GitLab Runner you most likely configured it to use your server's shell commands.
This means that all commands are run in context of local user (ie. gitlab_runner or gitlab_ci_multi_runner).
It also means that most probably in your Docker container you don't have the Ruby runtime installed.
You will have to install it:
-```
+
+```yaml
staging:
- type: deploy
+ stage: deploy
+ script:
- apt-get update -yq
- apt-get install -y ruby-dev
- gem install dpl
@@ -53,24 +67,31 @@ staging:
- master
```
-The first line `apt-get update -yq` updates the list of available packages, where second `apt-get install -y ruby-dev` install `Ruby` runtime on system.
+The first line `apt-get update -yq` updates the list of available packages,
+where second `apt-get install -y ruby-dev` installs the Ruby runtime on system.
The above example is valid for all Debian-compatible systems.
-### Usage in staging and production
-It's pretty common in developer workflow to have staging (development) and production environment.
-If we consider above example: we would like to deploy `master` branch to `staging` and `all tags` to `production` environment.
+## Usage in staging and production
+
+It's pretty common in the development workflow to have staging (development) and
+production environments
+
+Let's consider the following example: we would like to deploy the `master`
+branch to `staging` and all tags to the `production` environment.
The final `.gitlab-ci.yml` for that setup would look like this:
-```
+```yaml
staging:
- type: deploy
+ stage: deploy
+ script:
- gem install dpl
- dpl --provider=heroku --app=my-app-staging --api-key=$HEROKU_STAGING_API_KEY
only:
- master
-
+
production:
- type: deploy
+ stage: deploy
+ script:
- gem install dpl
- dpl --provider=heroku --app=my-app-production --api-key=$HEROKU_PRODUCTION_API_KEY
only:
@@ -78,21 +99,28 @@ production:
```
We created two deploy jobs that are executed on different events:
+
1. `staging` is executed for all commits that were pushed to `master` branch,
2. `production` is executed for all pushed tags.
We also use two secure variables:
+
1. `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app,
2. `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app.
-### Storing API keys
-In GitLab CI 7.12 a new feature was introduced: Secure Variables.
-Secure Variables can added by going to `Project > Variables > Add Variable`.
-**This feature requires `gitlab-runner` with version equal or greater than 0.4.0.**
-The variables that are defined in the project settings are sent along with the build script to the runner.
-The secure variables are stored out of the repository. Never store secrets in your projects' .gitlab-ci.yml.
-It is also important that secret's value is hidden in the build log.
+## Storing API keys
+
+Secure Variables can added by going to your project's
+**Settings ➔ Pipelines ➔ Secret variables**. The variables that are defined
+in the project settings are sent along with the build script to the Runner.
+The secure variables are stored out of the repository. Never store secrets in
+your project's `.gitlab-ci.yml`. It is also important that the secret's value
+is hidden in the job log.
+
+You access added variable by prefixing it's name with `$` (on non-Windows runners)
+or `%` (for Windows Batch runners):
-You access added variable by prefixing it's name with `$` (on non-Windows runners) or `%` (for Windows Batch runners):
1. `$SECRET_VARIABLE` - use it for non-Windows runners
2. `%SECRET_VARIABLE%` - use it for Windows Batch runners
+
+Read more about the [CI variables](../../variables/README.md).
diff --git a/doc/ci/examples/deployment/composer-npm-deploy.md b/doc/ci/examples/deployment/composer-npm-deploy.md
new file mode 100644
index 00000000000..b9f0485290e
--- /dev/null
+++ b/doc/ci/examples/deployment/composer-npm-deploy.md
@@ -0,0 +1,156 @@
+## Running Composer and NPM scripts with deployment via SCP
+
+This guide covers the building dependencies of a PHP project while compiling assets via an NPM script.
+
+While is possible to create your own image with custom PHP and Node JS versions, for brevity, we will use an existing [Docker image](https://hub.docker.com/r/tetraweb/php/) that contains both PHP and NodeJS installed.
+
+
+```yaml
+image: tetraweb/php
+```
+
+The next step is to install zip/unzip packages and make composer available. We will place these in the `before_script` section:
+
+```yaml
+before_script:
+ - apt-get update
+ - apt-get install zip unzip
+ - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
+ - php composer-setup.php
+ - php -r "unlink('composer-setup.php');"
+```
+
+This will make sure we have all requirements ready. Next, we want to run `composer install` to fetch all PHP dependencies and `npm install` to load node packages, then run the `npm` script. We need to append them into `before_script` section:
+
+```yaml
+before_script:
+ # ...
+ - php composer.phar install
+ - npm install
+ - npm run deploy
+```
+
+In this particular case, the `npm deploy` script is a Gulp script that does the following:
+
+1. Compile CSS & JS
+2. Create sprites
+3. Copy various assets (images, fonts) around
+4. Replace some strings
+
+All these operations will put all files into a `build` folder, which is ready to be deployed to a live server.
+
+### How to transfer files to a live server?
+
+You have multiple options: rsync, scp, sftp and so on. For now, we will use scp.
+
+To make this work, you need to add a GitLab Secret Variable (accessible on _gitlab.example/your-project-name/variables_). That variable will be called `STAGING_PRIVATE_KEY` and it's the **private** ssh key of your server.
+
+#### Security tip
+
+Create a user that has access **only** to the folder that needs to be updated!
+
+After you create that variable, you need to make sure that key will be added to the docker container on run:
+
+```yaml
+before_script:
+ # - ....
+ - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
+ - mkdir -p ~/.ssh
+ - eval $(ssh-agent -s)
+ - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
+```
+
+In order, this means that:
+
+1. We check if the `ssh-agent` is available and we install it if it's not;
+2. We create the `~/.ssh` folder;
+3. We make sure we're running bash;
+4. We disable host checking (we don't ask for user accept when we first connect to a server; and since every job will equal a first connect, we kind of need this)
+
+And this is basically all you need in the `before_script` section.
+
+## How to deploy things?
+
+As we stated above, we need to deploy the `build` folder from the docker image to our server. To do so, we create a new job:
+
+```yaml
+stage_deploy:
+ artifacts:
+ paths:
+ - build/
+ only:
+ - dev
+ script:
+ - ssh-add <(echo "$STAGING_PRIVATE_KEY")
+ - ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp"
+ - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp
+ - ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live"
+ - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old"
+```
+
+### What's going on here?
+
+1. `only:dev` means that this build will run only when something is pushed to the `dev` branch. You can remove this block completely and have everything be ran on every push (but probably this is something you don't want)
+2. `ssh-add ...` we will add that private key you added on the web UI to the docker container
+3. We will connect via `ssh` and create a new `_tmp` folder
+4. We will connect via `scp` and upload the `build` folder (which was generated by a `npm` script) to our previously created `_tmp` folder
+5. We will connect again to `ssh` and move the `live` folder to an `_old` folder, then move `_tmp` to `live`.
+6. We connect to ssh and remove the `_old` folder
+
+What's the deal with the artifacts? We just tell GitLab CI to keep the `build` directory (later on, you can download that as needed).
+
+#### Why we do it this way?
+
+If you're using this only for stage server, you could do this in two steps:
+
+```yaml
+- ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/live/*"
+- scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/live
+```
+
+The problem is that there will be a small period of time when you won't have the app on your server.
+
+So we use so many steps because we want to make sure that at any given time we have a functional app in place.
+
+## Where to go next?
+
+Since this was a WordPress project, I gave real life code snippets. Some ideas you can pursuit:
+
+- Having a slightly different script for `master` branch will allow you to deploy to a production server from that branch and to a stage server from any other branches;
+- Instead of pushing it live, you can push it to WordPress official repo (with creating a SVN commit & stuff);
+- You could generate i18n text domains on the fly.
+
+---
+
+Our final `.gitlab-ci.yml` will look like this:
+
+```yaml
+image: tetraweb/php
+
+before_script:
+ - apt-get update
+ - apt-get install zip unzip
+ - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
+ - php composer-setup.php
+ - php -r "unlink('composer-setup.php');"
+ - php composer.phar install
+ - npm install
+ - npm run deploy
+ - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
+ - mkdir -p ~/.ssh
+ - eval $(ssh-agent -s)
+ - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
+
+stage_deploy:
+ artifacts:
+ paths:
+ - build/
+ only:
+ - dev
+ script:
+ - ssh-add <(echo "$STAGING_PRIVATE_KEY")
+ - ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp"
+ - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp
+ - ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live"
+ - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old"
+```
diff --git a/doc/ci/examples/php.md b/doc/ci/examples/php.md
index 175e9d79904..f2dd12b67d3 100644
--- a/doc/ci/examples/php.md
+++ b/doc/ci/examples/php.md
@@ -15,10 +15,10 @@ This will allow us to test PHP projects against different versions of PHP.
However, not everything is plug 'n' play, you still need to configure some
things manually.
-As with every build, you need to create a valid `.gitlab-ci.yml` describing the
+As with every job, you need to create a valid `.gitlab-ci.yml` describing the
build environment.
-Let's first specify the PHP image that will be used for the build process
+Let's first specify the PHP image that will be used for the job process
(you can read more about what an image means in the Runner's lingo reading
about [Using Docker images](../docker/using_docker_images.md#what-is-image)).
@@ -40,7 +40,7 @@ repository with the following content:
#!/bin/bash
# We need to install dependencies only for Docker
-[[ ! -e /.dockerenv ]] && [[ ! -e /.dockerinit ]] && exit 0
+[[ ! -e /.dockerenv ]] && exit 0
set -xe
@@ -58,8 +58,8 @@ docker-php-ext-install pdo_mysql
```
You might wonder what `docker-php-ext-install` is. In short, it is a script
-provided by the official php docker image that you can use to easilly install
-extensions. For more information read the the documentation at
+provided by the official php docker image that you can use to easily install
+extensions. For more information read the documentation at
<https://hub.docker.com/r/_/php/>.
Now that we created the script that contains all prerequisites for our build
@@ -142,7 +142,7 @@ Of course, `my_php.ini` must be present in the root directory of your repository
## Test PHP projects using the Shell executor
-The shell executor runs your builds in a terminal session on your server.
+The shell executor runs your job in a terminal session on your server.
Thus, in order to test your projects you first need to make sure that all
dependencies are installed.
@@ -235,7 +235,11 @@ cache:
before_script:
# Install composer dependencies
-- curl --silent --show-error https://getcomposer.org/installer | php
+- wget https://composer.github.io/installer.sig -O - -q | tr -d '\n' > installer.sig
+- php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
+- php -r "if (hash_file('SHA384', 'composer-setup.php') === file_get_contents('installer.sig')) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
+- php composer-setup.php
+- php -r "unlink('composer-setup.php'); unlink('installer.sig');"
- php composer.phar install
...
@@ -276,7 +280,7 @@ that runs on [GitLab.com](https://gitlab.com) using our publicly available
[shared runners](../runners/README.md).
Want to hack on it? Simply fork it, commit and push your changes. Within a few
-moments the changes will be picked by a public runner and the build will begin.
+moments the changes will be picked by a public runner and the job will begin.
[php-hub]: https://hub.docker.com/r/_/php/
[phpenv]: https://github.com/phpenv/phpenv
diff --git a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
index e4d3970deac..73aebaf6d7f 100644
--- a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
@@ -55,11 +55,11 @@ You can do this through the [Dashboard](https://dashboard.heroku.com/).
### Create runner
First install [Docker Engine](https://docs.docker.com/installation/).
To build this project you also need to have [GitLab Runner](https://about.gitlab.com/gitlab-ci/#gitlab-runner).
-You can use public runners available on `gitlab.com/ci`, but you can register your own:
+You can use public runners available on `gitlab.com`, but you can register your own:
```
gitlab-ci-multi-runner register \
--non-interactive \
- --url "https://gitlab.com/ci/" \
+ --url "https://gitlab.com/" \
--registration-token "PROJECT_REGISTRATION_TOKEN" \
--description "python-3.5" \
--executor "docker" \
diff --git a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
index 08c10d391ea..6fa64a67e82 100644
--- a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
@@ -34,7 +34,7 @@ production:
This project has three jobs:
1. `test` - used to test Rails application,
2. `staging` - used to automatically deploy staging environment every push to `master` branch
-3. `production` - used to automatically deploy production environmnet for every created tag
+3. `production` - used to automatically deploy production environment for every created tag
### Store API keys
You'll need to create two variables in `Project > Variables`:
@@ -50,11 +50,11 @@ You can do this through the [Dashboard](https://dashboard.heroku.com/).
### Create runner
First install [Docker Engine](https://docs.docker.com/installation/).
To build this project you also need to have [GitLab Runner](https://about.gitlab.com/gitlab-ci/#gitlab-runner).
-You can use public runners available on `gitlab.com/ci`, but you can register your own:
+You can use public runners available on `gitlab.com`, but you can register your own:
```
gitlab-ci-multi-runner register \
--non-interactive \
- --url "https://gitlab.com/ci/" \
+ --url "https://gitlab.com/" \
--registration-token "PROJECT_REGISTRATION_TOKEN" \
--description "ruby-2.2" \
--executor "docker" \
diff --git a/doc/ci/examples/test-phoenix-application.md b/doc/ci/examples/test-phoenix-application.md
new file mode 100644
index 00000000000..150698ca04b
--- /dev/null
+++ b/doc/ci/examples/test-phoenix-application.md
@@ -0,0 +1,56 @@
+## Test a Phoenix application
+
+This example demonstrates the integration of Gitlab CI with Phoenix, Elixir and
+Postgres.
+
+### Add `.gitlab-ci.yml` file to project
+
+The following `.gitlab-ci.yml` should be added in the root of your
+repository to trigger CI:
+
+```yaml
+image: elixir:1.3
+
+services:
+ - postgres:9.6
+
+variables:
+ MIX_ENV: "test"
+
+before_script:
+ # Setup phoenix dependencies
+ - apt-get update
+ - apt-get install -y postgresql-client
+ - mix local.hex --force
+ - mix deps.get --only test
+ - mix ecto.reset
+
+test:
+ script:
+ - mix test
+```
+
+The variables will set the Mix environment to "test". The
+`before_script` will install `psql`, some Phoenix dependencies, and will also
+run your migrations.
+
+Finally, the test `script` will run your tests.
+
+### Update the Config Settings
+
+In `config/test.exs`, update the database hostname:
+
+```elixir
+config :my_app, MyApp.Repo,
+ hostname: if(System.get_env("CI"), do: "postgres", else: "localhost"),
+```
+
+### Add the Migrations Folder
+
+If you do not have any migrations yet, you will need to create an empty
+`.gitkeep` file in `priv/repo/migrations`.
+
+### Sources
+
+- https://medium.com/@nahtnam/using-phoenix-on-gitlab-ci-5a51eec81142
+- https://davejlong.com/ci-with-phoenix-and-gitlab/
diff --git a/doc/ci/examples/test-scala-application.md b/doc/ci/examples/test-scala-application.md
index 7412fdbbc78..09d83c33f95 100644
--- a/doc/ci/examples/test-scala-application.md
+++ b/doc/ci/examples/test-scala-application.md
@@ -1,11 +1,11 @@
-## Test a Scala application
+# Test and deploy to Heroku a Scala application
This example demonstrates the integration of Gitlab CI with Scala
applications using SBT. Checkout the example
[project](https://gitlab.com/gitlab-examples/scala-sbt) and
[build status](https://gitlab.com/gitlab-examples/scala-sbt/builds).
-### Add `.gitlab-ci.yml` file to project
+## Add `.gitlab-ci.yml` file to project
The following `.gitlab-ci.yml` should be added in the root of your
repository to trigger CI:
@@ -13,10 +13,14 @@ repository to trigger CI:
``` yaml
image: java:8
+stages:
+ - test
+ - deploy
+
before_script:
- apt-get update -y
- apt-get install apt-transport-https -y
- # Install SBT
+ ## Install SBT
- echo "deb http://dl.bintray.com/sbt/debian /" | tee -a /etc/apt/sources.list.d/sbt.list
- apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 642AC823
- apt-get update -y
@@ -24,8 +28,17 @@ before_script:
- sbt sbt-version
test:
+ stage: test
script:
- sbt clean coverage test coverageReport
+
+deploy:
+ stage: deploy
+ script:
+ - apt-get update -yq
+ - apt-get install rubygems ruby-dev -y
+ - gem install dpl
+ - dpl --provider=heroku --app=gitlab-play-sample-app --api-key=$HEROKU_API_KEY
```
The `before_script` installs [SBT](http://www.scala-sbt.org/) and
@@ -33,15 +46,31 @@ displays the version that is being used. The `test` stage executes SBT
to compile and test the project.
[scoverage](https://github.com/scoverage/sbt-scoverage) is used as an SBT
plugin to measure test coverage.
+The `deploy` stage automatically deploys the project to Heroku using dpl.
You can use other versions of Scala and SBT by defining them in
`build.sbt`.
-### Display test coverage in build
+## Display test coverage in job
Add the `Coverage was \[\d+.\d+\%\]` regular expression in the
-**Settings > Edit Project > Test coverage parsing** project setting to
-retrieve the test coverage rate from the build trace and have it
-displayed with your builds.
+**Settings ➔ Pipelines ➔ Coverage report** project setting to
+retrieve the [test coverage] rate from the build trace and have it
+displayed with your jobs.
+
+**Pipelines** must be enabled for this option to appear.
+
+## Heroku application
+
+A Heroku application is required. You can create one through the
+[Dashboard](https://dashboard.heroku.com/). Substitute `gitlab-play-sample-app`
+in the `.gitlab-ci.yml` file with your application's name.
+
+## Heroku API key
+
+You can look up your Heroku API key in your
+[account](https://dashboard.heroku.com/account). Add a secure [variable] with
+this value in **Project ➔ Variables** with key `HEROKU_API_KEY`.
-**Builds** must be enabled for this option to appear.
+[variable]: ../variables/README.md#user-defined-variables-secure-variables
+[test coverage]: ../../user/project/pipelines/settings.md#test-coverage-report-badge
diff --git a/doc/ci/git_submodules.md b/doc/ci/git_submodules.md
new file mode 100644
index 00000000000..36c6e153d95
--- /dev/null
+++ b/doc/ci/git_submodules.md
@@ -0,0 +1,97 @@
+# Using Git submodules with GitLab CI
+
+> **Notes:**
+- GitLab 8.12 introduced a new [CI job permissions model][newperms] and you
+ are encouraged to upgrade your GitLab instance if you haven't done already.
+ If you are **not** using GitLab 8.12 or higher, you would need to work your way
+ around submodules in order to access the sources of e.g., `gitlab.com/group/project`
+ with the use of [SSH keys](ssh_keys/README.md).
+- With GitLab 8.12 onward, your permissions are used to evaluate what a CI job
+ can access. More information about how this system works can be found in the
+ [Jobs permissions model](../user/permissions.md#jobs-permissions).
+- The HTTP(S) Git protocol [must be enabled][gitpro] in your GitLab instance.
+
+## Configuring the `.gitmodules` file
+
+If dealing with [Git submodules][gitscm], your project will probably have a file
+named `.gitmodules`.
+
+Let's consider the following example:
+
+1. Your project is located at `https://gitlab.com/secret-group/my-project`.
+1. To checkout your sources you usually use an SSH address like
+ `git@gitlab.com:secret-group/my-project.git`.
+1. Your project depends on `https://gitlab.com/group/project`, which you want
+ to include as a submodule.
+
+If you are using GitLab 8.12+ and your submodule is on the same GitLab server,
+you must update your `.gitmodules` file to use **relative URLs**.
+Since Git allows the usage of relative URLs for your `.gitmodules` configuration,
+this easily allows you to use HTTP(S) for cloning all your CI jobs and SSH
+for all your local checkouts. The `.gitmodules` would look like:
+
+```ini
+[submodule "project"]
+ path = project
+ url = ../../group/project.git
+```
+
+The above configuration will instruct Git to automatically deduce the URL that
+should be used when cloning sources. Whether you use HTTP(S) or SSH, Git will use
+that same channel and it will allow to make all your CI jobs use HTTP(S)
+(because GitLab CI only uses HTTP(S) for cloning your sources), and all your local
+clones will continue using SSH.
+
+For all other submodules not located on the same GitLab server, use the full
+HTTP(S) protocol URL:
+
+```ini
+[submodule "project-x"]
+ path = project-x
+ url = https://gitserver.com/group/project-x.git
+```
+
+Once `.gitmodules` is correctly configured, you can move on to
+[configuring your `.gitlab-ci.yml`](#using-git-submodules-in-your-ci-jobs).
+
+## Using Git submodules in your CI jobs
+
+There are a few steps you need to take in order to make submodules work
+correctly with your CI jobs:
+
+1. First, make sure you have used [relative URLs](#configuring-the-gitmodules-file)
+ for the submodules located in the same GitLab server.
+1. Next, if you are using `gitlab-ci-multi-runner` v1.10+, you can set the
+ `GIT_SUBMODULE_STRATEGY` variable to either `normal` or `recursive` to tell
+ the runner to fetch your submodules before the job:
+ ```yaml
+ variables:
+ GIT_SUBMODULE_STRATEGY: recursive
+ ```
+ See the [`.gitlab-ci.yml` reference](yaml/README.md#git-submodule-strategy)
+ for more details about `GIT_SUBMODULE_STRATEGY`.
+
+1. If you are using an older version of `gitlab-ci-multi-runner`, then use
+ `git submodule sync/update` in `before_script`:
+
+ ```yaml
+ before_script:
+ - git submodule sync --recursive
+ - git submodule update --init --recursive
+ ```
+
+ `--recursive` should be used in either both or none (`sync/update`) depending on
+ whether you have recursive submodules.
+
+The rationale to set the `sync` and `update` in `before_script` is because of
+the way Git submodules work. On a fresh Runner workspace, Git will set the
+submodule URL including the token in `.git/config`
+(or `.git/modules/<submodule>/config`) based on `.gitmodules` and the current
+remote URL. On subsequent jobs on the same Runner, `.git/config` is cached
+and already contains a full URL for the submodule, corresponding to the previous
+job, and to **a token from a previous job**. `sync` allows to force updating
+the full URL.
+
+[gitpro]: ../user/admin_area/settings/visibility_and_access_controls.md#enabled-git-access-protocols
+[gitscm]: https://git-scm.com/book/en/v2/Git-Tools-Submodules "Git submodules documentation"
+[newperms]: ../user/project/new_ci_build_permissions_model.md
diff --git a/doc/ci/img/builds_tab.png b/doc/ci/img/builds_tab.png
index 35780e277ae..2d7eec8a949 100644
--- a/doc/ci/img/builds_tab.png
+++ b/doc/ci/img/builds_tab.png
Binary files differ
diff --git a/doc/ci/img/cicd_pipeline_infograph.png b/doc/ci/img/cicd_pipeline_infograph.png
new file mode 100644
index 00000000000..9ddd4aa828b
--- /dev/null
+++ b/doc/ci/img/cicd_pipeline_infograph.png
Binary files differ
diff --git a/doc/ci/img/deployments_view.png b/doc/ci/img/deployments_view.png
new file mode 100644
index 00000000000..7ded0c97b72
--- /dev/null
+++ b/doc/ci/img/deployments_view.png
Binary files differ
diff --git a/doc/ci/img/environments_available_staging.png b/doc/ci/img/environments_available_staging.png
new file mode 100644
index 00000000000..5c031ad0d9d
--- /dev/null
+++ b/doc/ci/img/environments_available_staging.png
Binary files differ
diff --git a/doc/ci/img/environments_dynamic_groups.png b/doc/ci/img/environments_dynamic_groups.png
new file mode 100644
index 00000000000..0f42b368c5b
--- /dev/null
+++ b/doc/ci/img/environments_dynamic_groups.png
Binary files differ
diff --git a/doc/ci/img/environments_link_url.png b/doc/ci/img/environments_link_url.png
new file mode 100644
index 00000000000..44010f6aa6f
--- /dev/null
+++ b/doc/ci/img/environments_link_url.png
Binary files differ
diff --git a/doc/ci/img/environments_link_url_deployments.png b/doc/ci/img/environments_link_url_deployments.png
new file mode 100644
index 00000000000..4f90143527a
--- /dev/null
+++ b/doc/ci/img/environments_link_url_deployments.png
Binary files differ
diff --git a/doc/ci/img/environments_link_url_mr.png b/doc/ci/img/environments_link_url_mr.png
new file mode 100644
index 00000000000..64f134e0b0d
--- /dev/null
+++ b/doc/ci/img/environments_link_url_mr.png
Binary files differ
diff --git a/doc/ci/img/environments_manual_action_builds.png b/doc/ci/img/environments_manual_action_builds.png
new file mode 100644
index 00000000000..e7cf63a1031
--- /dev/null
+++ b/doc/ci/img/environments_manual_action_builds.png
Binary files differ
diff --git a/doc/ci/img/environments_manual_action_deployments.png b/doc/ci/img/environments_manual_action_deployments.png
new file mode 100644
index 00000000000..2b3f6f3edad
--- /dev/null
+++ b/doc/ci/img/environments_manual_action_deployments.png
Binary files differ
diff --git a/doc/ci/img/environments_manual_action_environments.png b/doc/ci/img/environments_manual_action_environments.png
new file mode 100644
index 00000000000..e0c07604e7f
--- /dev/null
+++ b/doc/ci/img/environments_manual_action_environments.png
Binary files differ
diff --git a/doc/ci/img/environments_manual_action_pipelines.png b/doc/ci/img/environments_manual_action_pipelines.png
new file mode 100644
index 00000000000..82bbae88027
--- /dev/null
+++ b/doc/ci/img/environments_manual_action_pipelines.png
Binary files differ
diff --git a/doc/ci/img/environments_manual_action_single_pipeline.png b/doc/ci/img/environments_manual_action_single_pipeline.png
new file mode 100644
index 00000000000..36337cb1870
--- /dev/null
+++ b/doc/ci/img/environments_manual_action_single_pipeline.png
Binary files differ
diff --git a/doc/ci/img/environments_monitoring.png b/doc/ci/img/environments_monitoring.png
new file mode 100644
index 00000000000..387b6c54b61
--- /dev/null
+++ b/doc/ci/img/environments_monitoring.png
Binary files differ
diff --git a/doc/ci/img/environments_mr_review_app.png b/doc/ci/img/environments_mr_review_app.png
new file mode 100644
index 00000000000..7bff84362a3
--- /dev/null
+++ b/doc/ci/img/environments_mr_review_app.png
Binary files differ
diff --git a/doc/ci/img/environments_terminal_button_on_index.png b/doc/ci/img/environments_terminal_button_on_index.png
new file mode 100644
index 00000000000..6f05b2aa343
--- /dev/null
+++ b/doc/ci/img/environments_terminal_button_on_index.png
Binary files differ
diff --git a/doc/ci/img/environments_terminal_button_on_show.png b/doc/ci/img/environments_terminal_button_on_show.png
new file mode 100644
index 00000000000..9469fab99ab
--- /dev/null
+++ b/doc/ci/img/environments_terminal_button_on_show.png
Binary files differ
diff --git a/doc/ci/img/environments_terminal_page.png b/doc/ci/img/environments_terminal_page.png
new file mode 100644
index 00000000000..fde1bf325a6
--- /dev/null
+++ b/doc/ci/img/environments_terminal_page.png
Binary files differ
diff --git a/doc/ci/img/environments_view.png b/doc/ci/img/environments_view.png
new file mode 100644
index 00000000000..821352188ef
--- /dev/null
+++ b/doc/ci/img/environments_view.png
Binary files differ
diff --git a/doc/ci/img/features_settings.png b/doc/ci/img/features_settings.png
deleted file mode 100644
index 38d7036f606..00000000000
--- a/doc/ci/img/features_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/img/permissions_settings.png b/doc/ci/img/permissions_settings.png
new file mode 100644
index 00000000000..1454c75fd24
--- /dev/null
+++ b/doc/ci/img/permissions_settings.png
Binary files differ
diff --git a/doc/ci/img/pipelines-goal.svg b/doc/ci/img/pipelines-goal.svg
new file mode 100644
index 00000000000..a925e2282a4
--- /dev/null
+++ b/doc/ci/img/pipelines-goal.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" standalone="yes"?>
+
+<svg version="1.1" viewBox="0.0 0.0 1091.020997375328 262.04461942257217" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="p.0"><path d="m0 0l1091.021 0l0 262.04462l-1091.021 0l0 -262.04462z" clip-rule="nonzero"></path></clipPath><g clip-path="url(#p.0)"><path fill="#000000" fill-opacity="0.0" d="m0 0l1091.021 0l0 262.04462l-1091.021 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m226.93439 3.7664042l860.7559 0l0 249.5748l-860.7559 0z" fill-rule="nonzero"></path><path stroke="#666666" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" stroke-dasharray="4.0,3.0" d="m226.93439 3.7664042l860.7559 0l0 249.5748l-860.7559 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m67.72179 27.199474l147.2126 0l0 39.464565l-147.2126 0z" fill-rule="nonzero"></path><path fill="#000000" d="m126.91313 49.353848l1.796875 0.453125q-0.5625 2.21875 -2.03125 3.390625q-1.46875 1.15625 -3.59375 1.15625q-2.203125 0 -3.578125 -0.890625q-1.375 -0.90625 -2.09375 -2.59375q-0.71875 -1.703125 -0.71875 -3.65625q0 -2.125 0.796875 -3.703125q0.8125 -1.578125 2.3125 -2.390625q1.5 -0.828125 3.296875 -0.828125q2.046875 0 3.4375 1.046875q1.390625 1.03125 1.9375 2.90625l-1.765625 0.421875q-0.46875 -1.484375 -1.375 -2.15625q-0.90625 -0.6875 -2.265625 -0.6875q-1.5625 0 -2.625 0.75q-1.046875 0.75 -1.484375 2.03125q-0.421875 1.265625 -0.421875 2.609375q0 1.734375 0.5 3.03125q0.515625 1.28125 1.578125 1.921875q1.078125 0.640625 2.3125 0.640625q1.515625 0 2.5625 -0.859375q1.046875 -0.875 1.421875 -2.59375zm3.5354462 4.765625l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.978302 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm15.547592 4.65625q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.735092 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277054 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm14.449646 5.875l0 -13.59375l2.71875 0l3.21875 9.625q0.4375 1.34375 0.640625 2.015625q0.234375 -0.75 0.734375 -2.1875l3.25 -9.453125l2.421875 0l0 13.59375l-1.734375 0l0 -11.390625l-3.953125 11.390625l-1.625 0l-3.9375 -11.578125l0 11.578125l-1.734375 0zm15.634552 0l0 -13.59375l6.03125 0q1.8125 0 2.75 0.359375q0.953125 0.359375 1.515625 1.296875q0.5625 0.921875 0.5625 2.046875q0 1.453125 -0.9375 2.453125q-0.921875 0.984375 -2.890625 1.25q0.71875 0.34375 1.09375 0.671875q0.78125 0.734375 1.484375 1.8125l2.375 3.703125l-2.265625 0l-1.796875 -2.828125q-0.796875 -1.21875 -1.3125 -1.875q-0.5 -0.65625 -0.90625 -0.90625q-0.40625 -0.265625 -0.8125 -0.359375q-0.3125 -0.078125 -1.015625 -0.078125l-2.078125 0l0 6.046875l-1.796875 0zm1.796875 -7.59375l3.859375 0q1.234375 0 1.921875 -0.25q0.703125 -0.265625 1.0625 -0.828125q0.375 -0.5625 0.375 -1.21875q0 -0.96875 -0.703125 -1.578125q-0.703125 -0.625 -2.21875 -0.625l-4.296875 0l0 4.5z" fill-rule="nonzero"></path><path fill="#efefef" d="m765.3307 106.94125l147.21265 0l0 59.74803l-147.21265 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m765.3307 106.94125l147.21265 0l0 59.74803l-147.21265 0z" fill-rule="nonzero"></path><path fill="#000000" d="m800.99805 132.73526l0 -13.593742l4.6875 0q1.578125 0 2.421875 0.1875q1.15625 0.265625 1.984375 0.96875q1.078125 0.921875 1.609375 2.34375q0.53125 1.40625 0.53125 3.21875q0 1.546875 -0.359375 2.7499924q-0.359375 1.1875 -0.921875 1.984375q-0.5625 0.78125 -1.234375 1.234375q-0.671875 0.4375 -1.625 0.671875q-0.953125 0.234375 -2.1875 0.234375l-4.90625 0zm1.796875 -1.609375l2.90625 0q1.34375 0 2.109375 -0.25q0.765625 -0.25 1.21875 -0.703125q0.640625 -0.640625 1.0 -1.71875q0.359375 -1.0781174 0.359375 -2.6249924q0 -2.125 -0.703125 -3.265625q-0.703125 -1.15625 -1.703125 -1.546875q-0.71875 -0.28125 -2.328125 -0.28125l-2.859375 0l0 10.390617zm18.207336 -1.5625l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.7343674q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.43749237l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.7031174l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.110107 9.656242l0 -13.640617l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.5156174 -0.546875 2.7343674q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.656242q0 1.9062424 0.765625 2.8124924q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.9218674q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm8.828857 4.8749924l0 -13.593742l1.671875 0l0 13.593742l-1.671875 0zm3.5510254 -4.9218674q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.9062424 -0.578125 2.9999924q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8124924zm1.71875 0q0 1.8906174 0.828125 2.8281174q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.8906174q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.203857 8.718742l-0.171875 -1.5625q0.546875 0.140625 0.953125 0.140625q0.546875 0 0.875 -0.1875q0.34375 -0.1875 0.5625 -0.515625q0.15625 -0.25 0.5 -1.25q0.046875 -0.140625 0.15625 -0.40625l-3.734375 -9.874992l1.796875 0l2.046875 5.7187424q0.40625 1.078125 0.71875 2.28125q0.28125 -1.15625 0.6875 -2.25l2.09375 -5.7499924l1.671875 0l-3.75 10.031242q-0.59375 1.625 -0.9375 2.234375q-0.4375 0.828125 -1.015625 1.203125q-0.578125 0.390625 -1.375 0.390625q-0.484375 0 -1.078125 -0.203125zm18.245789 -5.296875l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.6562424l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.7499924q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm0.9020996 -3.4218674q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.9062424 -0.578125 2.9999924q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8124924zm1.71875 0q0 1.8906174 0.828125 2.8281174q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.8906174q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125z" fill-rule="nonzero"></path><path fill="#000000" d="m808.1591 150.36026l1.6875 -0.140625q0.125 1.015625 0.5625 1.671875q0.4375 0.65625 1.359375 1.0625q0.9375 0.40625 2.09375 0.40625q1.03125 0 1.8125 -0.3125q0.796875 -0.3125 1.1875 -0.84375q0.390625 -0.53125 0.390625 -1.15625q0 -0.640625 -0.375 -1.109375q-0.375 -0.484375 -1.234375 -0.8125q-0.546875 -0.21875 -2.421875 -0.65625q-1.875 -0.453125 -2.625 -0.859375q-0.96875 -0.515625 -1.453125 -1.265625q-0.46875 -0.75 -0.46875 -1.6875q0 -1.03125 0.578125 -1.921875q0.59375 -0.90625 1.703125 -1.359375q1.125 -0.46875 2.5 -0.46875q1.515625 0 2.671875 0.484375q1.15625 0.484375 1.765625 1.4375q0.625 0.9375 0.671875 2.140625l-1.71875 0.125q-0.140625 -1.28125 -0.953125 -1.9375q-0.796875 -0.671875 -2.359375 -0.671875q-1.625 0 -2.375 0.609375q-0.75 0.59375 -0.75 1.4375q0 0.734375 0.53125 1.203125q0.515625 0.46875 2.703125 0.96875q2.203125 0.5 3.015625 0.875q1.1875 0.546875 1.75 1.390625q0.578125 0.828125 0.578125 1.921875q0 1.09375 -0.625 2.0625q-0.625 0.953125 -1.796875 1.484375q-1.15625 0.53125 -2.609375 0.53125q-1.84375 0 -3.09375 -0.53125q-1.25 -0.546875 -1.96875 -1.625q-0.703125 -1.078125 -0.734375 -2.453125zm16.490417 2.875l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm7.9645386 0.28125q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm3.7819824 5.75l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.313232 -6.578125l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.1292114 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm10.078796 0.8125l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875z" fill-rule="nonzero"></path><path fill="#efefef" d="m925.54333 177.39108l147.21252 0l0 59.74803l-147.21252 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m925.54333 177.39108l147.21252 0l0 59.74803l-147.21252 0z" fill-rule="nonzero"></path><path fill="#000000" d="m961.2107 203.18509l0 -13.59375l4.6875 0q1.578125 0 2.421875 0.1875q1.15625 0.265625 1.984375 0.96875q1.078125 0.921875 1.609375 2.34375q0.53125 1.40625 0.53125 3.21875q0 1.546875 -0.359375 2.75q-0.359375 1.1875 -0.921875 1.984375q-0.5625 0.78125 -1.234375 1.234375q-0.671875 0.4375 -1.625 0.671875q-0.953125 0.234375 -2.1875 0.234375l-4.90625 0zm1.796875 -1.609375l2.90625 0q1.34375 0 2.109375 -0.25q0.765625 -0.25 1.21875 -0.703125q0.640625 -0.640625 1.0 -1.71875q0.359375 -1.078125 0.359375 -2.625q0 -2.125 -0.703125 -3.265625q-0.703125 -1.15625 -1.703125 -1.546875q-0.71875 -0.28125 -2.328125 -0.28125l-2.859375 0l0 10.390625zm18.207275 -1.5625l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.110107 9.65625l0 -13.640625l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.515625 -0.546875 2.734375q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.65625q0 1.90625 0.765625 2.8125q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.921875q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm8.828857 4.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm3.5510864 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.203796 8.71875l-0.171875 -1.5625q0.546875 0.140625 0.953125 0.140625q0.546875 0 0.875 -0.1875q0.34375 -0.1875 0.5625 -0.515625q0.15625 -0.25 0.5 -1.25q0.046875 -0.140625 0.15625 -0.40625l-3.734375 -9.875l1.796875 0l2.046875 5.71875q0.40625 1.078125 0.71875 2.28125q0.28125 -1.15625 0.6875 -2.25l2.09375 -5.75l1.671875 0l-3.75 10.03125q-0.59375 1.625 -0.9375 2.234375q-0.4375 0.828125 -1.015625 1.203125q-0.578125 0.390625 -1.375 0.390625q-0.484375 0 -1.078125 -0.203125zm18.24585 -5.296875l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm0.90197754 -3.421875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125z" fill-rule="nonzero"></path><path fill="#000000" d="m956.0228 225.18509l0 -13.59375l5.125 0q1.359375 0 2.078125 0.125q1.0 0.171875 1.671875 0.640625q0.671875 0.46875 1.078125 1.3125q0.421875 0.84375 0.421875 1.84375q0 1.734375 -1.109375 2.9375q-1.09375 1.203125 -3.984375 1.203125l-3.484375 0l0 5.53125l-1.796875 0zm1.796875 -7.140625l3.515625 0q1.75 0 2.46875 -0.640625q0.734375 -0.65625 0.734375 -1.828125q0 -0.859375 -0.4375 -1.46875q-0.421875 -0.609375 -1.125 -0.796875q-0.453125 -0.125 -1.671875 -0.125l-3.484375 0l0 4.859375zm10.4122925 7.140625l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm5.6033325 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm15.672607 4.921875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375zm15.719421 4.921875l0 -1.453125q-1.140625 1.671875 -3.125 1.671875q-0.859375 0 -1.625 -0.328125q-0.75 -0.34375 -1.125 -0.84375q-0.359375 -0.5 -0.515625 -1.234375q-0.09375 -0.5 -0.09375 -1.5625l0 -6.109375l1.671875 0l0 5.46875q0 1.3125 0.09375 1.765625q0.15625 0.65625 0.671875 1.03125q0.515625 0.375 1.265625 0.375q0.75 0 1.40625 -0.375q0.65625 -0.390625 0.921875 -1.046875q0.28125 -0.671875 0.28125 -1.9375l0 -5.28125l1.671875 0l0 9.859375l-1.5 0zm10.360107 -3.609375l1.640625 0.21875q-0.265625 1.6875 -1.375 2.65625q-1.109375 0.953125 -2.734375 0.953125q-2.015625 0 -3.25 -1.3125q-1.21875 -1.328125 -1.21875 -3.796875q0 -1.59375 0.515625 -2.78125q0.53125 -1.203125 1.609375 -1.796875q1.09375 -0.609375 2.359375 -0.609375q1.609375 0 2.625 0.8125q1.015625 0.8125 1.3125 2.3125l-1.625 0.25q-0.234375 -1.0 -0.828125 -1.5q-0.59375 -0.5 -1.421875 -0.5q-1.265625 0 -2.0625 0.90625q-0.78125 0.90625 -0.78125 2.859375q0 1.984375 0.765625 2.890625q0.765625 0.890625 1.984375 0.890625q0.984375 0 1.640625 -0.59375q0.65625 -0.609375 0.84375 -1.859375zm6.546875 2.109375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426636 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5042114 -4.921875q0 -2.734375 1.531311 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.281311 -1.328125 -1.281311 -3.8125zm1.718811 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.28186 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m57.989502 117.082985l156.94489 0l0 39.46456l-156.94489 0z" fill-rule="nonzero"></path><path fill="#000000" d="m71.518036 144.00298l0 -13.59375l2.71875 0l3.21875 9.625q0.4375 1.34375 0.640625 2.015625q0.234375 -0.75 0.734375 -2.1875l3.25 -9.453125l2.421875 0l0 13.59375l-1.734375 0l0 -11.390625l-3.953125 11.390625l-1.625 0l-3.9375 -11.578125l0 11.578125l-1.734375 0zm22.134552 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.094467 5.875l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm5.931427 0.8125l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm16.047592 1.9375l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm17.949646 4.375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm0.90205383 -3.421875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm14.621521 4.921875l0 -13.59375l2.71875 0l3.21875 9.625q0.4375 1.34375 0.640625 2.015625q0.234375 -0.75 0.734375 -2.1875l3.25 -9.453125l2.421875 0l0 13.59375l-1.734375 0l0 -11.390625l-3.953125 11.390625l-1.625 0l-3.9375 -11.578125l0 11.578125l-1.734375 0zm21.822052 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm3.4069672 2.0l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277054 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.094467 5.875l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m5.0104985 187.5328l209.95276 0l0 39.46457l-209.95276 0z" fill-rule="nonzero"></path><path fill="#000000" d="m34.188858 214.4528l0 -13.59375l2.71875 0l3.21875 9.625q0.4375 1.34375 0.640625 2.015625q0.234375 -0.75 0.734375 -2.1875l3.25 -9.453125l2.421875 0l0 13.59375l-1.734375 0l0 -11.390625l-3.953125 11.390625l-1.625 0l-3.9375 -11.578125l0 11.578125l-1.734375 0zm22.134552 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.094467 5.875l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm5.931427 0.8125l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm16.047592 1.9375l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm17.949646 4.375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm0.90205383 -3.421875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm14.684021 4.921875l0 -13.59375l5.125 0q1.359375 0 2.078125 0.125q1.0 0.171875 1.671875 0.640625q0.671875 0.46875 1.078125 1.3125q0.421875 0.84375 0.421875 1.84375q0 1.734375 -1.109375 2.9375q-1.09375 1.203125 -3.984375 1.203125l-3.484375 0l0 5.53125l-1.796875 0zm1.796875 -7.140625l3.515625 0q1.75 0 2.46875 -0.640625q0.734375 -0.65625 0.734375 -1.828125q0 -0.859375 -0.4375 -1.46875q-0.421875 -0.609375 -1.125 -0.796875q-0.453125 -0.125 -1.671875 -0.125l-3.484375 0l0 4.859375zm10.412323 7.140625l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm5.603302 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm15.672592 4.921875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375zm15.719467 4.921875l0 -1.453125q-1.140625 1.671875 -3.125 1.671875q-0.859375 0 -1.625 -0.328125q-0.75 -0.34375 -1.125 -0.84375q-0.359375 -0.5 -0.515625 -1.234375q-0.09375 -0.5 -0.09375 -1.5625l0 -6.109375l1.671875 0l0 5.46875q0 1.3125 0.09375 1.765625q0.15625 0.65625 0.671875 1.03125q0.515625 0.375 1.265625 0.375q0.75 0 1.40625 -0.375q0.65625 -0.390625 0.921875 -1.046875q0.28125 -0.671875 0.28125 -1.9375l0 -5.28125l1.671875 0l0 9.859375l-1.5 0zm10.360092 -3.609375l1.640625 0.21875q-0.265625 1.6875 -1.375 2.65625q-1.109375 0.953125 -2.734375 0.953125q-2.015625 0 -3.25 -1.3125q-1.21875 -1.328125 -1.21875 -3.796875q0 -1.59375 0.515625 -2.78125q0.53125 -1.203125 1.609375 -1.796875q1.09375 -0.609375 2.359375 -0.609375q1.609375 0 2.625 0.8125q1.015625 0.8125 1.3125 2.3125l-1.625 0.25q-0.234375 -1.0 -0.828125 -1.5q-0.59375 -0.5 -1.421875 -0.5q-1.265625 0 -2.0625 0.90625q-0.78125 0.90625 -0.78125 2.859375q0 1.984375 0.765625 2.890625q0.765625 0.890625 1.984375 0.890625q0.984375 0 1.640625 -0.59375q0.65625 -0.609375 0.84375 -1.859375zm6.546875 2.109375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426788 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5041962 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281967 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm10.813217 0l0 -1.90625l1.90625 0l0 1.90625q0 1.046875 -0.375 1.6875q-0.375 0.65625 -1.171875 1.0l-0.46875 -0.71875q0.53125 -0.21875 0.78125 -0.671875q0.25 -0.453125 0.28125 -1.296875l-0.953125 0z" fill-rule="nonzero"></path><path fill="#000000" d="m51.19565 236.4528l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.161606 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm3.7819672 5.75l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm14.887146 5.109375l0 -8.546875l-1.484375 0l0 -1.3125l1.484375 0l0 -1.046875q0 -0.984375 0.171875 -1.46875q0.234375 -0.65625 0.84375 -1.046875q0.609375 -0.40625 1.703125 -0.40625q0.703125 0 1.5625 0.15625l-0.25 1.46875q-0.515625 -0.09375 -0.984375 -0.09375q-0.765625 0 -1.078125 0.328125q-0.3125 0.3125 -0.3125 1.203125l0 0.90625l1.921875 0l0 1.3125l-1.921875 0l0 8.546875l-1.65625 0zm4.152054 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.266342 4.921875l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm11.661606 0l0 -13.59375l6.03125 0q1.8125 0 2.75 0.359375q0.953125 0.359375 1.515625 1.296875q0.5625 0.921875 0.5625 2.046875q0 1.453125 -0.9375 2.453125q-0.921875 0.984375 -2.890625 1.25q0.71875 0.34375 1.09375 0.671875q0.78125 0.734375 1.484375 1.8125l2.375 3.703125l-2.265625 0l-1.796875 -2.828125q-0.796875 -1.21875 -1.3125 -1.875q-0.5 -0.65625 -0.90625 -0.90625q-0.40625 -0.265625 -0.8125 -0.359375q-0.3125 -0.078125 -1.015625 -0.078125l-2.078125 0l0 6.046875l-1.796875 0zm1.796875 -7.59375l3.859375 0q1.234375 0 1.921875 -0.25q0.703125 -0.265625 1.0625 -0.828125q0.375 -0.5625 0.375 -1.21875q0 -0.96875 -0.703125 -1.578125q-0.703125 -0.625 -2.21875 -0.625l-4.296875 0l0 4.5zm18.176071 4.421875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.078842 5.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm10.926071 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm15.547592 4.65625q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm3.4069672 2.0l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm16.75 -0.234375l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.547592 5.875l0 -1.90625l1.90625 0l0 1.90625q0 1.046875 -0.375 1.6875q-0.375 0.65625 -1.171875 1.0l-0.46875 -0.71875q0.53125 -0.21875 0.78125 -0.671875q0.25 -0.453125 0.28125 -1.296875l-0.953125 0zm9.304108 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.266342 4.921875l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" d="m88.11708 258.45282l0 -13.593765l2.71875 0l3.21875 9.625q0.4375 1.34375 0.640625 2.0156403q0.234375 -0.75001526 0.734375 -2.1875153l3.25 -9.453125l2.421875 0l0 13.593765l-1.734375 0l0 -11.39064l-3.953125 11.39064l-1.625 0l-3.9375 -11.57814l0 11.57814l-1.734375 0zm21.822052 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.0312653q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.3281403 0.09375 2.9531403q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.7187653q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.67189026 0.5 1.1250153q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.1562653q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm4.078842 4.9375153l0 -9.85939l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625153l-1.671875 0l0 -6.0000153q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.3750153l-1.671875 0zm16.828842 0l0 -1.453125q-1.140625 1.671875 -3.125 1.671875q-0.859375 0 -1.625 -0.328125q-0.75 -0.34375 -1.125 -0.84375q-0.359375 -0.5 -0.515625 -1.234375q-0.09375 -0.50001526 -0.09375 -1.5625153l0 -6.109375l1.671875 0l0 5.46875q0 1.3125 0.09375 1.765625q0.15625 0.65626526 0.671875 1.0312653q0.515625 0.375 1.265625 0.375q0.75 0 1.40625 -0.375q0.65625 -0.390625 0.921875 -1.0468903q0.28125 -0.671875 0.28125 -1.9375l0 -5.28125l1.671875 0l0 9.85939l-1.5 0zm10.360092 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.0312653q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.3281403 0.09375 2.9531403q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.7187653q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.67189026 0.5 1.1250153q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.1562653q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm4.047592 4.9375153l0 -13.593765l1.671875 0l0 13.593765l-1.671875 0zm13.015625 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.9843903l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71876526 0.078125 0.92189026q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5114288 1.5l0 -9.85939l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.1562653l-1.671875 0zm6.243927 -11.687515l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.687515l0 -9.85939l1.671875 0l0 9.85939l-1.671875 0zm3.8323212 0.8125l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.4687653 -1.109375 -3.5156403q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.51564q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.9218903q0 1.953125 0.765625 2.8437653q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.89064026 0.78125 -2.7812653q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.000717 5.9218903l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.4687653 -1.109375 -3.5156403q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.51564q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.9218903q0 1.953125 0.765625 2.8437653q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.89064026 0.78125 -2.7812653q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm16.047592 1.9375l1.71875 0.21875q-0.40625 1.5000153 -1.515625 2.3437653q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.7343903q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.4843903q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.5468903zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.094467 5.8750153l0 -9.85939l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.1562653l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m214.93439 46.93176l13.599762 0l0 0.062992096l13.612839 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m214.93439 46.93176l13.599747 0l0 0.062992096l7.612854 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m236.14699 48.646484l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"></path><path fill="#efefef" d="m242.13387 17.057743l147.2126 0l0 59.748028l-147.2126 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m242.13387 17.057743l147.2126 0l0 59.748028l-147.2126 0z" fill-rule="nonzero"></path><path fill="#000000" d="m296.38846 53.851757l0 -13.59375l5.109375 0q1.546875 0 2.484375 0.40625q0.953125 0.40625 1.484375 1.265625q0.53125 0.859375 0.53125 1.796875q0 0.875 -0.46875 1.65625q-0.46875 0.765625 -1.4375 1.234375q1.234375 0.359375 1.890625 1.234375q0.671875 0.875 0.671875 2.0625q0 0.953125 -0.40625 1.78125q-0.390625 0.8125 -0.984375 1.265625q-0.59375 0.4375 -1.5 0.671875q-0.890625 0.21875 -2.1875 0.21875l-5.1875 0zm1.796875 -7.890625l2.9375 0q1.203125 0 1.71875 -0.15625q0.6875 -0.203125 1.03125 -0.671875q0.359375 -0.46875 0.359375 -1.1875q0 -0.671875 -0.328125 -1.1875q-0.328125 -0.515625 -0.9375 -0.703125q-0.59375 -0.203125 -2.0625 -0.203125l-2.71875 0l0 4.109375zm0 6.28125l3.390625 0q0.875 0 1.21875 -0.0625q0.625 -0.109375 1.046875 -0.359375q0.421875 -0.265625 0.6875 -0.765625q0.265625 -0.5 0.265625 -1.140625q0 -0.765625 -0.390625 -1.328125q-0.390625 -0.5625 -1.078125 -0.78125q-0.6875 -0.234375 -1.984375 -0.234375l-3.15625 0l0 4.671875zm16.959198 1.609375l0 -1.453125q-1.140625 1.671875 -3.125 1.671875q-0.859375 0 -1.625 -0.328125q-0.75 -0.34375 -1.125 -0.84375q-0.359375 -0.5 -0.515625 -1.234375q-0.09375 -0.5 -0.09375 -1.5625l0 -6.109375l1.671875 0l0 5.46875q0 1.3125 0.09375 1.765625q0.15625 0.65625 0.671875 1.03125q0.515625 0.375 1.265625 0.375q0.75 0 1.40625 -0.375q0.65625 -0.390625 0.921875 -1.046875q0.28125 -0.671875 0.28125 -1.9375l0 -5.28125l1.671875 0l0 9.859375l-1.5 0zm3.9382324 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.097931 0l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm10.566711 0l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375z" fill-rule="nonzero"></path><path fill="#efefef" d="m408.5328 17.057743l147.21262 0l0 59.748028l-147.21262 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m408.5328 17.057743l147.21262 0l0 59.748028l-147.21262 0z" fill-rule="nonzero"></path><path fill="#000000" d="m455.20813 40.258007l1.796875 0l0 7.84375q0 2.0625 -0.46875 3.265625q-0.453125 1.203125 -1.671875 1.96875q-1.203125 0.75 -3.171875 0.75q-1.90625 0 -3.125 -0.65625q-1.21875 -0.65625 -1.734375 -1.90625q-0.515625 -1.25 -0.515625 -3.421875l0 -7.84375l1.796875 0l0 7.84375q0 1.765625 0.328125 2.609375q0.328125 0.84375 1.125 1.296875q0.8125 0.453125 1.96875 0.453125q1.984375 0 2.828125 -0.890625q0.84375 -0.90625 0.84375 -3.46875l0 -7.84375zm4.332306 13.59375l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm10.391357 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm7.785431 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm10.382233 1.5l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438202 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#efefef" d="m594.1181 37.30971l147.21259 0l0 59.748028l-147.21259 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m594.1181 37.30971l147.21259 0l0 59.748028l-147.21259 0z" fill-rule="nonzero"></path><path fill="#000000" d="m625.4092 63.103725l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm4.6676636 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm14.031982 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277039 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813232 6.6875l1.609375 0.24999619q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.2812462q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3124962 -0.46875 3.2656212q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.3906212zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.109375l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.6657715 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7351074 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426636 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5042114 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" d="m654.5047 85.10372l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438232 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#efefef" d="m584.5302 27.199474l147.21259 0l0 59.748035l-147.21259 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m584.5302 27.199474l147.21259 0l0 59.748035l-147.21259 0z" fill-rule="nonzero"></path><path fill="#000000" d="m615.8212 52.99349l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm4.6677246 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm14.031921 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.2771 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813171 6.6875l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.109375l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.6658325 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7350464 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5427246 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5041504 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" d="m644.9168 74.99349l0 -12.000004l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.000004l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438171 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375038l1.65625 -1.0l0 3.4375038l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#efefef" d="m574.93176 17.057743l147.21259 0l0 59.748028l-147.21259 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m574.93176 17.057743l147.21259 0l0 59.748028l-147.21259 0z" fill-rule="nonzero"></path><path fill="#000000" d="m606.22284 42.851757l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm4.6676636 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm14.031982 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277039 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813232 6.6875l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.109375l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.6657715 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7351074 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426636 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5042114 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" d="m635.31836 64.85175l0 -11.999996l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 11.999996l-1.796875 0zm14.474121 -3.1718712l1.71875 0.21875q-0.40625 1.5 -1.515625 2.3437462q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.3281212q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438232 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.7343712 -1.40625 1.1406212q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.7968712 -1.28125 -2.3593712zm13.65625 1.4375l0.234375 1.4843712q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.7499962q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m389.34647 46.93176l9.593231 0l0 0.062992096l9.58786 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m389.34647 46.93176l9.593201 0l0 0.062992096l3.5878906 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m402.52756 48.646484l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m555.7454 46.93176l9.593201 0l0 0.062992096l9.587891 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m555.7454 46.93176l9.593201 0l0 0.062992096l3.5878906 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m568.9265 48.646484l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m214.96326 207.26509l355.29132 0l0 0.06298828l355.29138 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m214.96326 207.26509l355.29132 0l0 0.06298828l349.29138 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m919.54596 208.97981l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m214.93439 136.81526l14.661118 0l0 0.06300354l14.661713 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m214.93439 136.81526l14.661133 0l0 0.06300354l8.661697 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m238.25722 138.53l4.538101 -1.6517334l-4.538101 -1.6517334z" fill-rule="evenodd"></path><path fill="#efefef" d="m244.25691 106.94125l147.2126 0l0 59.74803l-147.2126 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m244.25691 106.94125l147.2126 0l0 59.74803l-147.2126 0z" fill-rule="nonzero"></path><path fill="#000000" d="m298.5115 143.73526l0 -13.59375l5.109375 0q1.546875 0 2.484375 0.40625q0.953125 0.40625 1.484375 1.265625q0.53125 0.859375 0.53125 1.796875q0 0.875 -0.46875 1.65625q-0.46875 0.765625 -1.4375 1.234375q1.234375 0.359375 1.890625 1.234375q0.671875 0.875 0.671875 2.0625q0 0.953125 -0.40625 1.78125q-0.390625 0.8125 -0.984375 1.265625q-0.59375 0.4375 -1.5 0.671875q-0.890625 0.21875 -2.1875 0.21875l-5.1875 0zm1.796875 -7.890625l2.9375 0q1.203125 0 1.71875 -0.15625q0.6875 -0.203125 1.03125 -0.671875q0.359375 -0.46875 0.359375 -1.1875q0 -0.671875 -0.328125 -1.1875q-0.328125 -0.515625 -0.9375 -0.703125q-0.59375 -0.203125 -2.0625 -0.203125l-2.71875 0l0 4.109375zm0 6.28125l3.390625 0q0.875 0 1.21875 -0.0625q0.625 -0.109375 1.046875 -0.359375q0.421875 -0.265625 0.6875 -0.765625q0.265625 -0.5 0.265625 -1.140625q0 -0.765625 -0.390625 -1.328125q-0.390625 -0.5625 -1.078125 -0.78125q-0.6875 -0.234375 -1.984375 -0.234375l-3.15625 0l0 4.671875zm16.959198 1.609375l0 -1.453125q-1.140625 1.671875 -3.125 1.671875q-0.859375 0 -1.625 -0.328125q-0.75 -0.34375 -1.125 -0.84375q-0.359375 -0.5 -0.515625 -1.234375q-0.09375 -0.5 -0.09375 -1.5625l0 -6.109375l1.671875 0l0 5.46875q0 1.3125 0.09375 1.765625q0.15625 0.65625 0.671875 1.03125q0.515625 0.375 1.265625 0.375q0.75 0 1.40625 -0.375q0.65625 -0.390625 0.921875 -1.046875q0.28125 -0.671875 0.28125 -1.9375l0 -5.28125l1.671875 0l0 9.859375l-1.5 0zm3.9382324 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.097931 0l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm10.566711 0l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375z" fill-rule="nonzero"></path><path fill="#efefef" d="m410.65585 106.94125l147.21262 0l0 59.74803l-147.21262 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m410.65585 106.94125l147.21262 0l0 59.74803l-147.21262 0z" fill-rule="nonzero"></path><path fill="#000000" d="m457.33118 130.14151l1.796875 0l0 7.84375q0 2.0625 -0.46875 3.265625q-0.453125 1.203125 -1.671875 1.96875q-1.203125 0.75 -3.171875 0.75q-1.90625 0 -3.125 -0.65625q-1.21875 -0.65625 -1.734375 -1.90625q-0.515625 -1.25 -0.515625 -3.421875l0 -7.84375l1.796875 0l0 7.84375q0 1.765625 0.328125 2.609375q0.328125 0.84375 1.125 1.296875q0.8125 0.453125 1.96875 0.453125q1.984375 0 2.828125 -0.890625q0.84375 -0.90625 0.84375 -3.46875l0 -7.84375zm4.332306 13.59375l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm10.391357 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm7.785431 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm10.382233 1.5l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438202 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#efefef" d="m596.24115 127.19322l147.21259 0l0 59.74803l-147.21259 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m596.24115 127.19322l147.21259 0l0 59.74803l-147.21259 0z" fill-rule="nonzero"></path><path fill="#000000" d="m627.5322 152.98723l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm4.6676636 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm14.031982 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277039 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813232 6.6875l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.109375l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.6657715 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7351074 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426636 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5042114 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" d="m656.62775 174.98723l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438232 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#efefef" d="m586.65326 117.082985l147.21259 0l0 59.748024l-147.21259 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m586.65326 117.082985l147.21259 0l0 59.748024l-147.21259 0z" fill-rule="nonzero"></path><path fill="#000000" d="m617.9443 142.877l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm4.6677246 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm14.031921 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.2771 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813171 6.6875l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.109375l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.6658325 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7350464 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5427246 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5041504 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" d="m647.03986 164.877l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438171 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#efefef" d="m577.0548 106.94125l147.21259 0l0 59.74803l-147.21259 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m577.0548 106.94125l147.21259 0l0 59.74803l-147.21259 0z" fill-rule="nonzero"></path><path fill="#000000" d="m608.3459 132.73526l0 -13.593742l1.8125 0l0 13.593742l-1.8125 0zm4.6676636 0l0 -9.859367l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0624924l-1.671875 0l0 -5.9999924q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.3749924l-1.671875 0zm14.031982 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.6562424l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.7499924q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277039 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.7343674q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.43749237l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.7031174l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813232 6.6874924l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.5156174q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515617q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.9218674q0 1.9531174 0.765625 2.8437424q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.7812424q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.1093674l0 -9.859367l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.1562424l-1.671875 0zm12.6657715 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.9531174q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.2343674q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.7187424q-0.90625 0.35936737 -2.734375 0.6249924q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.6093674zm7.7351074 3.4374924l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.6562424l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.7499924q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426636 -10.187492l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.687492l0 -9.859367l1.671875 0l0 9.859367l-1.671875 0zm3.5042114 -4.9218674q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.9062424 -0.578125 2.9999924q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8124924zm1.71875 0q0 1.8906174 0.828125 2.8281174q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.8906174q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.9218674l0 -9.859367l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0624924l-1.671875 0l0 -5.9999924q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.3749924l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" d="m637.4414 154.73526l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438232 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m391.4695 136.81526l9.593231 0l0 0.06300354l9.58786 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m391.46954 136.81526l9.593201 0l0 0.06300354l3.5878906 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m404.65063 138.53l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m557.86847 136.81526l9.593201 0l0 0.06300354l9.587891 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m557.86847 136.81526l9.593201 0l0 0.06300354l3.5878906 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m571.04956 138.53l4.538147 -1.6517334l-4.538147 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m724.2674 136.81526l20.531738 0l0 0.06300354l20.539124 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m724.2674 136.81526l20.531738 0l0 0.06300354l14.539124 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m759.33826 138.53l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"></path></g></svg>
+
diff --git a/doc/ci/img/pipelines.png b/doc/ci/img/pipelines.png
new file mode 100644
index 00000000000..a604fcb2587
--- /dev/null
+++ b/doc/ci/img/pipelines.png
Binary files differ
diff --git a/doc/ci/img/pipelines_grouped.png b/doc/ci/img/pipelines_grouped.png
new file mode 100644
index 00000000000..06f52e03320
--- /dev/null
+++ b/doc/ci/img/pipelines_grouped.png
Binary files differ
diff --git a/doc/ci/img/pipelines_index.png b/doc/ci/img/pipelines_index.png
new file mode 100644
index 00000000000..3b522a9c5e4
--- /dev/null
+++ b/doc/ci/img/pipelines_index.png
Binary files differ
diff --git a/doc/ci/img/pipelines_mini_graph.png b/doc/ci/img/pipelines_mini_graph.png
new file mode 100644
index 00000000000..042c8ffeef5
--- /dev/null
+++ b/doc/ci/img/pipelines_mini_graph.png
Binary files differ
diff --git a/doc/ci/img/pipelines_mini_graph_simple.png b/doc/ci/img/pipelines_mini_graph_simple.png
new file mode 100644
index 00000000000..eb36c09b2d4
--- /dev/null
+++ b/doc/ci/img/pipelines_mini_graph_simple.png
Binary files differ
diff --git a/doc/ci/img/pipelines_mini_graph_sorting.png b/doc/ci/img/pipelines_mini_graph_sorting.png
new file mode 100644
index 00000000000..3a4e5453360
--- /dev/null
+++ b/doc/ci/img/pipelines_mini_graph_sorting.png
Binary files differ
diff --git a/doc/ci/img/prometheus_environment_detail_with_metrics.png b/doc/ci/img/prometheus_environment_detail_with_metrics.png
new file mode 100644
index 00000000000..214b10624a9
--- /dev/null
+++ b/doc/ci/img/prometheus_environment_detail_with_metrics.png
Binary files differ
diff --git a/doc/ci/img/types-of-pipelines.svg b/doc/ci/img/types-of-pipelines.svg
new file mode 100644
index 00000000000..b63b5f56ba6
--- /dev/null
+++ b/doc/ci/img/types-of-pipelines.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" standalone="yes"?>
+
+<svg version="1.1" viewBox="0.0 0.0 740.6272965879265 293.7795275590551" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="p.0"><path d="m0 0l740.6273 0l0 293.77954l-740.6273 0l0 -293.77954z" clip-rule="nonzero"></path></clipPath><g clip-path="url(#p.0)"><path fill="#000000" fill-opacity="0.0" d="m0 0l740.6273 0l0 293.77954l-740.6273 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m176.05511 4.632546l282.4567 0l0 129.10236l-282.4567 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" stroke-dasharray="4.0,3.0" d="m176.05511 4.632546l282.4567 0l0 129.10236l-282.4567 0z" fill-rule="nonzero"></path><path fill="#ff0000" d="m283.34512 115.88928l1.796875 0.453125q-0.5625 2.21875 -2.03125 3.390625q-1.46875 1.15625 -3.59375 1.15625q-2.203125 0 -3.578125 -0.890625q-1.375 -0.90625 -2.09375 -2.59375q-0.71875 -1.703125 -0.71875 -3.65625q0 -2.125 0.796875 -3.703125q0.8125 -1.578125 2.3125 -2.390625q1.5 -0.828125 3.296875 -0.828125q2.046875 0 3.4375 1.046875q1.390625 1.03125 1.9375 2.90625l-1.765625 0.421875q-0.46875 -1.484375 -1.375 -2.15625q-0.90625 -0.6875 -2.265625 -0.6875q-1.5625 0 -2.625 0.75q-1.046875 0.75 -1.484375 2.03125q-0.421875 1.265625 -0.421875 2.609375q0 1.734375 0.5 3.03125q0.515625 1.28125 1.578125 1.921875q1.078125 0.640625 2.3125 0.640625q1.515625 0 2.5625 -0.859375q1.046875 -0.875 1.421875 -2.59375zm4.066681 4.765625l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm10.069733 0l0 -13.59375l5.125 0q1.359375 0 2.078125 0.125q1.0 0.171875 1.671875 0.640625q0.671875 0.46875 1.078125 1.3125q0.421875 0.84375 0.421875 1.84375q0 1.734375 -1.109375 2.9375q-1.09375 1.203125 -3.984375 1.203125l-3.484375 0l0 5.53125l-1.796875 0zm1.796875 -7.140625l3.515625 0q1.75 0 2.46875 -0.640625q0.734375 -0.65625 0.734375 -1.828125q0 -0.859375 -0.4375 -1.46875q-0.421875 -0.609375 -1.125 -0.796875q-0.453125 -0.125 -1.671875 -0.125l-3.484375 0l0 4.859375zm10.443573 -4.546875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.1292114 3.78125l0 -13.640625l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.515625 -0.546875 2.734375q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.65625q0 1.90625 0.765625 2.8125q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.921875q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm15.610077 1.703125l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.078857 5.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm4.191681 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.1292114 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm17.125702 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875z" fill-rule="nonzero"></path><path fill="#f3f3f3" d="m482.78796 22.986877l110.11023 0l0 59.74803l-110.11023 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m482.78796 22.986877l110.11023 0l0 59.74803l-110.11023 0z" fill-rule="nonzero"></path><path fill="#434343" d="m499.90414 48.78089l0 -13.59375l4.6875 0q1.578125 0 2.421875 0.1875q1.15625 0.265625 1.984375 0.96875q1.078125 0.921875 1.609375 2.34375q0.53125 1.40625 0.53125 3.21875q0 1.546875 -0.359375 2.75q-0.359375 1.1875 -0.921875 1.984375q-0.5625 0.78125 -1.234375 1.234375q-0.671875 0.4375 -1.625 0.671875q-0.953125 0.234375 -2.1875 0.234375l-4.90625 0zm1.796875 -1.609375l2.90625 0q1.34375 0 2.109375 -0.25q0.765625 -0.25 1.21875 -0.703125q0.640625 -0.640625 1.0 -1.71875q0.359375 -1.078125 0.359375 -2.625q0 -2.125 -0.703125 -3.265625q-0.703125 -1.15625 -1.703125 -1.546875q-0.71875 -0.28125 -2.328125 -0.28125l-2.859375 0l0 10.390625zm18.207306 -1.5625l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.110107 9.65625l0 -13.640625l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.515625 -0.546875 2.734375q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.65625q0 1.90625 0.765625 2.8125q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.921875q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm8.828857 4.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm3.5510864 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.203796 8.71875l-0.171875 -1.5625q0.546875 0.140625 0.953125 0.140625q0.546875 0 0.875 -0.1875q0.34375 -0.1875 0.5625 -0.515625q0.15625 -0.25 0.5 -1.25q0.046875 -0.140625 0.15625 -0.40625l-3.734375 -9.875l1.796875 0l2.046875 5.71875q0.40625 1.078125 0.71875 2.28125q0.28125 -1.15625 0.6875 -2.25l2.09375 -5.75l1.671875 0l-3.75 10.03125q-0.59375 1.625 -0.9375 2.234375q-0.4375 0.828125 -1.015625 1.203125q-0.578125 0.390625 -1.375 0.390625q-0.484375 0 -1.078125 -0.203125zm18.245789 -5.296875l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm0.9020996 -3.421875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125z" fill-rule="nonzero"></path><path fill="#434343" d="m507.0652 66.40589l1.6875 -0.140625q0.125 1.015625 0.5625 1.671875q0.4375 0.65625 1.359375 1.0625q0.9375 0.40625 2.09375 0.40625q1.03125 0 1.8125 -0.3125q0.796875 -0.3125 1.1875 -0.84375q0.390625 -0.53125 0.390625 -1.15625q0 -0.640625 -0.375 -1.109375q-0.375 -0.484375 -1.234375 -0.8125q-0.546875 -0.21875 -2.421875 -0.65625q-1.875 -0.453125 -2.625 -0.859375q-0.96875 -0.515625 -1.453125 -1.265625q-0.46875 -0.75 -0.46875 -1.6875q0 -1.03125 0.578125 -1.921875q0.59375 -0.90625 1.703125 -1.359375q1.125 -0.46875 2.5 -0.46875q1.515625 0 2.671875 0.484375q1.15625 0.484375 1.765625 1.4375q0.625 0.9375 0.671875 2.140625l-1.71875 0.125q-0.140625 -1.28125 -0.953125 -1.9375q-0.796875 -0.671875 -2.359375 -0.671875q-1.625 0 -2.375 0.609375q-0.75 0.59375 -0.75 1.4375q0 0.734375 0.53125 1.203125q0.515625 0.46875 2.703125 0.96875q2.203125 0.5 3.015625 0.875q1.1875 0.546875 1.75 1.390625q0.578125 0.828125 0.578125 1.921875q0 1.09375 -0.625 2.0625q-0.625 0.953125 -1.796875 1.484375q-1.15625 0.53125 -2.609375 0.53125q-1.84375 0 -3.09375 -0.53125q-1.25 -0.546875 -1.96875 -1.625q-0.703125 -1.078125 -0.734375 -2.453125zm16.490417 2.875l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm7.9645996 0.28125q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm3.7819214 5.75l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.313232 -6.578125l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.1292114 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm10.078796 0.8125l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875z" fill-rule="nonzero"></path><path fill="#f3f3f3" d="m606.1778 23.019379l110.11023 0l0 59.74803l-110.11023 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m606.1778 23.019379l110.11023 0l0 59.74803l-110.11023 0z" fill-rule="nonzero"></path><path fill="#434343" d="m623.29395 48.813393l0 -13.59375l4.6875 0q1.578125 0 2.421875 0.1875q1.15625 0.265625 1.984375 0.96875q1.078125 0.921875 1.609375 2.34375q0.53125 1.40625 0.53125 3.21875q0 1.546875 -0.359375 2.75q-0.359375 1.1875 -0.921875 1.984375q-0.5625 0.78125 -1.234375 1.234375q-0.671875 0.4375 -1.625 0.671875q-0.953125 0.234375 -2.1875 0.234375l-4.90625 0zm1.796875 -1.609375l2.90625 0q1.34375 0 2.109375 -0.25q0.765625 -0.25 1.21875 -0.703125q0.640625 -0.640625 1.0 -1.71875q0.359375 -1.078125 0.359375 -2.625q0 -2.125 -0.703125 -3.265625q-0.703125 -1.15625 -1.703125 -1.546875q-0.71875 -0.28125 -2.328125 -0.28125l-2.859375 0l0 10.390625zm18.207336 -1.5625l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.110107 9.65625l0 -13.640625l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.515625 -0.546875 2.734375q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.65625q0 1.90625 0.765625 2.8125q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.921875q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm8.828857 4.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm3.5510254 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.203857 8.71875l-0.171875 -1.5625q0.546875 0.140625 0.953125 0.140625q0.546875 0 0.875 -0.1875q0.34375 -0.1875 0.5625 -0.515625q0.15625 -0.25 0.5 -1.25q0.046875 -0.140625 0.15625 -0.40625l-3.734375 -9.875l1.796875 0l2.046875 5.71875q0.40625 1.078125 0.71875 2.28125q0.28125 -1.15625 0.6875 -2.25l2.09375 -5.75l1.671875 0l-3.75 10.03125q-0.59375 1.625 -0.9375 2.234375q-0.4375 0.828125 -1.015625 1.203125q-0.578125 0.390625 -1.375 0.390625q-0.484375 0 -1.078125 -0.203125zm18.245789 -5.296875l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm0.9020996 -3.421875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125z" fill-rule="nonzero"></path><path fill="#434343" d="m618.10614 70.81339l0 -13.59375l5.125 0q1.359375 0 2.078125 0.125q1.0 0.171875 1.671875 0.640625q0.671875 0.46875 1.078125 1.3125q0.421875 0.84375 0.421875 1.84375q0 1.734375 -1.109375 2.9375q-1.09375 1.203125 -3.984375 1.203125l-3.484375 0l0 5.53125l-1.796875 0zm1.796875 -7.140625l3.515625 0q1.75 0 2.46875 -0.640625q0.734375 -0.65625 0.734375 -1.828125q0 -0.859375 -0.4375 -1.46875q-0.421875 -0.609375 -1.125 -0.796875q-0.453125 -0.125 -1.671875 -0.125l-3.484375 0l0 4.859375zm10.4122925 7.140625l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm5.6033325 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm15.672546 4.921875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375zm15.719482 4.921875l0 -1.453125q-1.140625 1.671875 -3.125 1.671875q-0.859375 0 -1.625 -0.328125q-0.75 -0.34375 -1.125 -0.84375q-0.359375 -0.5 -0.515625 -1.234375q-0.09375 -0.5 -0.09375 -1.5625l0 -6.109375l1.671875 0l0 5.46875q0 1.3125 0.09375 1.765625q0.15625 0.65625 0.671875 1.03125q0.515625 0.375 1.265625 0.375q0.75 0 1.40625 -0.375q0.65625 -0.390625 0.921875 -1.046875q0.28125 -0.671875 0.28125 -1.9375l0 -5.28125l1.671875 0l0 9.859375l-1.5 0zm10.360107 -3.609375l1.640625 0.21875q-0.265625 1.6875 -1.375 2.65625q-1.109375 0.953125 -2.734375 0.953125q-2.015625 0 -3.25 -1.3125q-1.21875 -1.328125 -1.21875 -3.796875q0 -1.59375 0.515625 -2.78125q0.53125 -1.203125 1.609375 -1.796875q1.09375 -0.609375 2.359375 -0.609375q1.609375 0 2.625 0.8125q1.015625 0.8125 1.3125 2.3125l-1.625 0.25q-0.234375 -1.0 -0.828125 -1.5q-0.59375 -0.5 -1.421875 -0.5q-1.265625 0 -2.0625 0.90625q-0.78125 0.90625 -0.78125 2.859375q0 1.984375 0.765625 2.890625q0.765625 0.890625 1.984375 0.890625q0.984375 0 1.640625 -0.59375q0.65625 -0.609375 0.84375 -1.859375zm6.546875 2.109375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426636 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5042114 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#f3f3f3" d="m192.52992 22.986877l110.07875 0l0 59.74803l-110.07875 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m192.52992 22.986877l110.07875 0l0 59.74803l-110.07875 0z" fill-rule="nonzero"></path><path fill="#434343" d="m228.21759 59.78089l0 -13.59375l5.109375 0q1.546875 0 2.484375 0.40625q0.953125 0.40625 1.484375 1.265625q0.53125 0.859375 0.53125 1.796875q0 0.875 -0.46875 1.65625q-0.46875 0.765625 -1.4375 1.234375q1.234375 0.359375 1.890625 1.234375q0.671875 0.875 0.671875 2.0625q0 0.953125 -0.40625 1.78125q-0.390625 0.8125 -0.984375 1.265625q-0.59375 0.4375 -1.5 0.671875q-0.890625 0.21875 -2.1875 0.21875l-5.1875 0zm1.796875 -7.890625l2.9375 0q1.203125 0 1.71875 -0.15625q0.6875 -0.203125 1.03125 -0.671875q0.359375 -0.46875 0.359375 -1.1875q0 -0.671875 -0.328125 -1.1875q-0.328125 -0.515625 -0.9375 -0.703125q-0.59375 -0.203125 -2.0625 -0.203125l-2.71875 0l0 4.109375zm0 6.28125l3.390625 0q0.875 0 1.21875 -0.0625q0.625 -0.109375 1.046875 -0.359375q0.421875 -0.265625 0.6875 -0.765625q0.265625 -0.5 0.265625 -1.140625q0 -0.765625 -0.390625 -1.328125q-0.390625 -0.5625 -1.078125 -0.78125q-0.6875 -0.234375 -1.984375 -0.234375l-3.15625 0l0 4.671875zm16.959198 1.609375l0 -1.453125q-1.140625 1.671875 -3.125 1.671875q-0.859375 0 -1.625 -0.328125q-0.75 -0.34375 -1.125 -0.84375q-0.359375 -0.5 -0.515625 -1.234375q-0.09375 -0.5 -0.09375 -1.5625l0 -6.109375l1.671875 0l0 5.46875q0 1.3125 0.09375 1.765625q0.15625 0.65625 0.671875 1.03125q0.515625 0.375 1.265625 0.375q0.75 0 1.40625 -0.375q0.65625 -0.390625 0.921875 -1.046875q0.28125 -0.671875 0.28125 -1.9375l0 -5.28125l1.671875 0l0 9.859375l-1.5 0zm3.9382172 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.097946 0l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm10.566681 0l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375z" fill-rule="nonzero"></path><path fill="#f3f3f3" d="m331.2466 43.238846l110.078735 0l0 59.74803l-110.078735 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m331.2466 43.238846l110.078735 0l0 59.74803l-110.078735 0z" fill-rule="nonzero"></path><path fill="#434343" d="m343.97073 69.03286l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm4.667694 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm14.031952 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277069 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813202 6.6875l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.109375l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.665802 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.735077 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426941 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.504181 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#434343" d="m373.06628 91.03286l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438202 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#f3f3f3" d="m324.0777 33.12861l110.078766 0l0 59.74803l-110.078766 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m324.0777 33.12861l110.078766 0l0 59.74803l-110.078766 0z" fill-rule="nonzero"></path><path fill="#434343" d="m336.80185 58.922623l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm4.667694 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm14.031952 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277069 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813202 6.6875l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.109375l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.6657715 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.8593445 0.3125 -1.8437195 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.0312195 -0.25 2.9843445 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.9062195 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.2499695 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.7343445 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.9687195 0 1.7187195 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7351074 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426636 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5042114 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281952 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#434343" d="m365.8974 80.92262l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474091 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438232 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#f3f3f3" d="m316.90097 22.986877l110.078735 0l0 59.74803l-110.078735 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m316.90097 22.986877l110.078735 0l0 59.74803l-110.078735 0z" fill-rule="nonzero"></path><path fill="#434343" d="m354.05658 59.78089l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438202 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm0.8551941 -1.4375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m302.60867 52.860893l7.165344 0l0 0.062992096l7.165344 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m302.60864 52.860893l7.1653748 0l0 0.062992096l1.1653442 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m310.93936 54.57562l4.5381165 -1.6517334l-4.5381165 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m426.9797 52.860893l27.904388 0l0 0.062992096l27.906647 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m426.9797 52.860893l27.904388 0l0 0.062992096l21.906616 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m476.7907 54.57562l4.5381165 -1.6517334l-4.5381165 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m592.8982 52.860893l6.6398315 0l0 0.062992096l6.6514893 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m592.8982 52.860893l6.6398315 0l0 0.062992096l0.6515503 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m600.1896 54.57562l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"></path><path fill="#f3f3f3" d="m26.104986 22.986877l110.11024 0l0 59.74803l-110.11024 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m26.104986 22.986877l110.11024 0l0 59.74803l-110.11024 0z" fill-rule="nonzero"></path><path fill="#434343" d="m70.03193 55.015266l1.796875 0.453125q-0.5625 2.21875 -2.03125 3.390625q-1.46875 1.15625 -3.59375 1.15625q-2.203125 0 -3.5781212 -0.890625q-1.375 -0.90625 -2.09375 -2.59375q-0.71875 -1.703125 -0.71875 -3.65625q0 -2.125 0.796875 -3.703125q0.8125 -1.578125 2.3125 -2.390625q1.4999962 -0.828125 3.2968712 -0.828125q2.046875 0 3.4375 1.046875q1.390625 1.03125 1.9375 2.90625l-1.765625 0.421875q-0.46875 -1.484375 -1.375 -2.15625q-0.90625 -0.6875 -2.265625 -0.6875q-1.5625 0 -2.6249962 0.75q-1.046875 0.75 -1.484375 2.03125q-0.421875 1.265625 -0.421875 2.609375q0 1.734375 0.5 3.03125q0.515625 1.28125 1.578125 1.921875q1.0781212 0.640625 2.3124962 0.640625q1.515625 0 2.5625 -0.859375q1.046875 -0.875 1.421875 -2.59375zm2.9260712 -0.15625q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm15.672592 4.921875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375zm16.016342 1.75l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m136.21523 52.860893l28.15747 0l0 0.062992096l28.157486 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m136.21523 52.860893l28.15747 0l0 0.062992096l22.157486 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m186.53018 54.57562l4.538101 -1.6517334l-4.538101 -1.6517334z" fill-rule="evenodd"></path><path fill="#f3f3f3" d="m26.104986 120.98688l110.11024 0l0 59.74803l-110.11024 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m26.104986 120.98688l110.11024 0l0 59.74803l-110.11024 0z" fill-rule="nonzero"></path><path fill="#434343" d="m50.508137 146.78088l0 -13.59375l6.03125 0q1.8125 0 2.75 0.359375q0.953125 0.359375 1.515625 1.296875q0.5625 0.921875 0.5625 2.046875q0 1.453125 -0.9375 2.453125q-0.921875 0.984375 -2.890625 1.25q0.71875 0.34375 1.09375 0.671875q0.78125 0.734375 1.484375 1.8125l2.375 3.703125l-2.265625 0l-1.796875 -2.828125q-0.796875 -1.21875 -1.3125 -1.875q-0.5 -0.65625 -0.90625 -0.90625q-0.40625 -0.265625 -0.8125 -0.359375q-0.3125 -0.078125 -1.015625 -0.078125l-2.078125 0l0 6.046875l-1.796875 0zm1.796875 -7.59375l3.859375 0q1.234375 0 1.921875 -0.25q0.703125 -0.265625 1.0625 -0.828125q0.375 -0.5625 0.375 -1.21875q0 -0.96875 -0.703125 -1.578125q-0.703125 -0.625 -2.21875 -0.625l-4.296875 0l0 4.5zm18.176067 4.421875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.2656212 -1.328125 -1.2656212 -3.734375q0 -2.484375 1.2656212 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.078842 5.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm10.613571 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7351 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.4062576 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.6562576 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277054 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm15.500717 5.875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375z" fill-rule="nonzero"></path><path fill="#434343" d="m70.03193 164.01526l1.796875 0.453125q-0.5625 2.21875 -2.03125 3.390625q-1.46875 1.15625 -3.59375 1.15625q-2.203125 0 -3.5781212 -0.890625q-1.375 -0.90625 -2.09375 -2.59375q-0.71875 -1.703125 -0.71875 -3.65625q0 -2.125 0.796875 -3.703125q0.8125 -1.578125 2.3125 -2.390625q1.4999962 -0.828125 3.2968712 -0.828125q2.046875 0 3.4375 1.046875q1.390625 1.03125 1.9375 2.90625l-1.765625 0.421875q-0.46875 -1.484375 -1.375 -2.15625q-0.90625 -0.6875 -2.265625 -0.6875q-1.5625 0 -2.6249962 0.75q-1.046875 0.75 -1.484375 2.03125q-0.421875 1.265625 -0.421875 2.609375q0 1.734375 0.5 3.03125q0.515625 1.28125 1.578125 1.921875q1.0781212 0.640625 2.3124962 0.640625q1.515625 0 2.5625 -0.859375q1.046875 -0.875 1.421875 -2.59375zm2.9260712 -0.15625q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm15.672592 4.921875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375zm16.016342 1.75l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m136.21523 150.86089l28.15747 0l0 -98.01574l28.157486 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m136.21523 150.86089l28.15747 0l0 -98.01574l22.157486 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m186.53018 54.496876l4.538101 -1.6517296l-4.538101 -1.6517334z" fill-rule="evenodd"></path><path fill="#f3f3f3" d="m26.104986 190.98688l110.11024 0l0 59.74803l-110.11024 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m26.104986 190.98688l110.11024 0l0 59.74803l-110.11024 0z" fill-rule="nonzero"></path><path fill="#434343" d="m50.508137 216.78088l0 -13.59375l6.03125 0q1.8125 0 2.75 0.359375q0.953125 0.359375 1.515625 1.296875q0.5625 0.921875 0.5625 2.046875q0 1.453125 -0.9375 2.453125q-0.921875 0.984375 -2.890625 1.25q0.71875 0.34375 1.09375 0.671875q0.78125 0.734375 1.484375 1.8125l2.375 3.703125l-2.265625 0l-1.796875 -2.828125q-0.796875 -1.21875 -1.3125 -1.875q-0.5 -0.65625 -0.90625 -0.90625q-0.40625 -0.265625 -0.8125 -0.359375q-0.3125 -0.078125 -1.015625 -0.078125l-2.078125 0l0 6.046875l-1.796875 0zm1.796875 -7.59375l3.859375 0q1.234375 0 1.921875 -0.25q0.703125 -0.265625 1.0625 -0.828125q0.375 -0.5625 0.375 -1.21875q0 -0.96875 -0.703125 -1.578125q-0.703125 -0.625 -2.21875 -0.625l-4.296875 0l0 4.5zm18.176067 4.421875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.2656212 -1.328125 -1.2656212 -3.734375q0 -2.484375 1.2656212 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.078842 5.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm10.613571 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7351 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.4062576 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.6562576 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277054 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm15.500717 5.875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375z" fill-rule="nonzero"></path><path fill="#434343" d="m70.03193 234.01526l1.796875 0.453125q-0.5625 2.21875 -2.03125 3.390625q-1.46875 1.15625 -3.59375 1.15625q-2.203125 0 -3.5781212 -0.890625q-1.375 -0.90625 -2.09375 -2.59375q-0.71875 -1.703125 -0.71875 -3.65625q0 -2.125 0.796875 -3.703125q0.8125 -1.578125 2.3125 -2.390625q1.4999962 -0.828125 3.2968712 -0.828125q2.046875 0 3.4375 1.046875q1.390625 1.03125 1.9375 2.90625l-1.765625 0.421875q-0.46875 -1.484375 -1.375 -2.15625q-0.90625 -0.6875 -2.265625 -0.6875q-1.5625 0 -2.6249962 0.75q-1.046875 0.75 -1.484375 2.03125q-0.421875 1.265625 -0.421875 2.609375q0 1.734375 0.5 3.03125q0.515625 1.28125 1.578125 1.921875q1.0781212 0.640625 2.3124962 0.640625q1.515625 0 2.5625 -0.859375q1.046875 -0.875 1.421875 -2.59375zm2.9260712 -0.15625q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm15.672592 4.921875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375zm16.016342 1.75l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m136.21523 220.86089l28.15747 0l0 -168.0l28.157486 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m136.21523 220.86089l28.15747 0l0 -168.0l22.157486 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m186.53018 54.512627l4.538101 -1.6517334l-4.538101 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m5.1522307 4.632546l165.85826 0l0 283.52756l-165.85826 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" stroke-dasharray="4.0,3.0" d="m5.1522307 4.632546l165.85826 0l0 283.52756l-165.85826 0z" fill-rule="nonzero"></path><path fill="#ff0000" d="m24.73604 275.0801l0 -13.59375l5.125 0q1.359375 0 2.078125 0.125q0.9999981 0.171875 1.6718731 0.640625q0.671875 0.46875 1.078125 1.3125q0.421875 0.84375 0.421875 1.84375q0 1.734375 -1.109375 2.9375q-1.09375 1.203125 -3.984373 1.203125l-3.484375 0l0 5.53125l-1.796875 0zm1.796875 -7.140625l3.515625 0q1.75 0 2.468748 -0.640625q0.734375 -0.65625 0.734375 -1.828125q0 -0.859375 -0.4375 -1.46875q-0.421875 -0.609375 -1.1249981 -0.796875q-0.453125 -0.125 -1.671875 -0.125l-3.484375 0l0 4.859375zm10.412321 7.140625l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm5.603302 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281967 -6.734375l0 -1.9375l1.65625 0l0 1.9375l-1.65625 0zm-2.125 15.484375l0.3125 -1.421875q0.5 0.125 0.796875 0.125q0.515625 0 0.765625 -0.34375q0.25 -0.328125 0.25 -1.6875l0 -10.359375l1.65625 0l0 10.390625q0 1.828125 -0.46875 2.546875q-0.59375 0.921875 -2.0 0.921875q-0.671875 0 -1.3125 -0.171875zm13.019821 -7.0l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm15.547592 2.265625l1.640625 0.21875q-0.265625 1.6875 -1.375 2.65625q-1.109375 0.953125 -2.734375 0.953125q-2.015625 0 -3.25 -1.3125q-1.21875 -1.328125 -1.21875 -3.796875q0 -1.59375 0.515625 -2.78125q0.53125 -1.203125 1.609375 -1.796875q1.09375 -0.609375 2.359375 -0.609375q1.609375 0 2.625 0.8125q1.015625 0.8125 1.3125 2.3125l-1.625 0.25q-0.234375 -1.0 -0.828125 -1.5q-0.59375 -0.5 -1.421875 -0.5q-1.265625 0 -2.0625 0.90625q-0.78125 0.90625 -0.78125 2.859375q0 1.984375 0.765625 2.890625q0.765625 0.890625 1.984375 0.890625q0.984375 0 1.640625 -0.59375q0.65625 -0.609375 0.84375 -1.859375zm6.546875 2.109375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm6.9291077 1.5l0 -13.59375l5.125 0q1.359375 0 2.078125 0.125q1.0 0.171875 1.671875 0.640625q0.671875 0.46875 1.078125 1.3125q0.421875 0.84375 0.421875 1.84375q0 1.734375 -1.109375 2.9375q-1.09375 1.203125 -3.984375 1.203125l-3.484375 0l0 5.53125l-1.796875 0zm1.796875 -7.140625l3.515625 0q1.75 0 2.46875 -0.640625q0.734375 -0.65625 0.734375 -1.828125q0 -0.859375 -0.4375 -1.46875q-0.421875 -0.609375 -1.125 -0.796875q-0.453125 -0.125 -1.671875 -0.125l-3.484375 0l0 4.859375zm10.443573 -4.546875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.129196 3.78125l0 -13.640625l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.515625 -0.546875 2.734375q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.65625q0 1.90625 0.765625 2.8125q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.921875q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm15.610092 1.703125l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.078842 5.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm4.191696 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.129196 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm17.125732 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m464.70865 4.632546l270.23624 0l0 129.10236l-270.23624 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" stroke-dasharray="4.0,3.0" d="m464.70865 4.632546l270.23624 0l0 129.10236l-270.23624 0z" fill-rule="nonzero"></path><path fill="#ff0000" d="m536.47687 120.65491l0 -13.59375l4.6875 0q1.578125 0 2.421875 0.1875q1.15625 0.265625 1.984375 0.96875q1.078125 0.921875 1.609375 2.34375q0.53125 1.40625 0.53125 3.21875q0 1.546875 -0.359375 2.75q-0.359375 1.1875 -0.921875 1.984375q-0.5625 0.78125 -1.234375 1.234375q-0.671875 0.4375 -1.625 0.671875q-0.953125 0.234375 -2.1875 0.234375l-4.90625 0zm1.796875 -1.609375l2.90625 0q1.34375 0 2.109375 -0.25q0.765625 -0.25 1.21875 -0.703125q0.640625 -0.640625 1.0 -1.71875q0.359375 -1.078125 0.359375 -2.625q0 -2.125 -0.703125 -3.265625q-0.703125 -1.15625 -1.703125 -1.546875q-0.71875 -0.28125 -2.328125 -0.28125l-2.859375 0l0 10.390625zm18.207336 -1.5625l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.110107 9.65625l0 -13.640625l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.515625 -0.546875 2.734375q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.65625q0 1.90625 0.765625 2.8125q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.921875q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm8.828857 4.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm3.5510254 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.203857 8.71875l-0.171875 -1.5625q0.546875 0.140625 0.953125 0.140625q0.546875 0 0.875 -0.1875q0.34375 -0.1875 0.5625 -0.515625q0.15625 -0.25 0.5 -1.25q0.046875 -0.140625 0.15625 -0.40625l-3.734375 -9.875l1.796875 0l2.046875 5.71875q0.40625 1.078125 0.71875 2.28125q0.28125 -1.15625 0.6875 -2.25l2.09375 -5.75l1.671875 0l-3.75 10.03125q-0.59375 1.625 -0.9375 2.234375q-0.4375 0.828125 -1.015625 1.203125q-0.578125 0.390625 -1.375 0.390625q-0.484375 0 -1.078125 -0.203125zm14.808289 -3.796875l0 -13.59375l5.125 0q1.359375 0 2.078125 0.125q1.0 0.171875 1.671875 0.640625q0.671875 0.46875 1.078125 1.3125q0.421875 0.84375 0.421875 1.84375q0 1.734375 -1.109375 2.9375q-1.09375 1.203125 -3.984375 1.203125l-3.484375 0l0 5.53125l-1.796875 0zm1.796875 -7.140625l3.515625 0q1.75 0 2.46875 -0.640625q0.734375 -0.65625 0.734375 -1.828125q0 -0.859375 -0.4375 -1.46875q-0.421875 -0.609375 -1.125 -0.796875q-0.453125 -0.125 -1.671875 -0.125l-3.484375 0l0 4.859375zm10.4436035 -4.546875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.1292114 3.78125l0 -13.640625l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.515625 -0.546875 2.734375q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.65625q0 1.90625 0.765625 2.8125q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.921875q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm15.610046 1.703125l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.078857 5.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm4.1917114 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.1292114 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm17.125671 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875z" fill-rule="nonzero"></path></g></svg>
+
diff --git a/doc/ci/img/view_on_env_blob.png b/doc/ci/img/view_on_env_blob.png
new file mode 100644
index 00000000000..f4fe99046f0
--- /dev/null
+++ b/doc/ci/img/view_on_env_blob.png
Binary files differ
diff --git a/doc/ci/img/view_on_env_mr.png b/doc/ci/img/view_on_env_mr.png
new file mode 100644
index 00000000000..47ddb40bdc1
--- /dev/null
+++ b/doc/ci/img/view_on_env_mr.png
Binary files differ
diff --git a/doc/ci/pipelines.md b/doc/ci/pipelines.md
index ca9b986a060..5a2b61fb0cb 100644
--- a/doc/ci/pipelines.md
+++ b/doc/ci/pipelines.md
@@ -1,75 +1,237 @@
-# Introduction to pipelines and builds
+# Introduction to pipelines and jobs
->**Note:**
-Introduced in GitLab 8.8.
+> Introduced in GitLab 8.8.
## Pipelines
-A pipeline is a group of [builds] that get executed in [stages] \(batches). All
-of the builds in a stage are executed in parallel (if there are enough
-concurrent [runners]), and if they all succeed, the pipeline moves on to the
-next stage. If one of the builds fails, the next stage is not (usually)
-executed.
+A pipeline is a group of [jobs][] that get executed in [stages][](batches).
+All of the jobs in a stage are executed in parallel (if there are enough
+concurrent [Runners]), and if they all succeed, the pipeline moves on to the
+next stage. If one of the jobs fails, the next stage is not (usually)
+executed. You can access the pipelines page in your project's **Pipelines** tab.
+
+In the following image you can see that the pipeline consists of four stages
+(`build`, `test`, `staging`, `production`) each one having one or more jobs.
+
+>**Note:**
+GitLab capitalizes the stages' names when shown in the [pipeline graphs](#pipeline-graphs).
+
+![Pipelines example](img/pipelines.png)
+
+## Types of pipelines
+
+There are three types of pipelines that often use the single shorthand of "pipeline". People often talk about them as if each one is "the" pipeline, but really, they're just pieces of a single, comprehensive pipeline.
+
+![Types of Pipelines](img/types-of-pipelines.svg)
-## Builds
+1. **CI Pipeline**: Build and test stages defined in `.gitlab-ci.yml`
+2. **Deploy Pipeline**: Deploy stage(s) defined in `.gitlab-ci.yml` The flow of deploying code to servers through various stages: e.g. development to staging to production
+3. **Project Pipeline**: Cross-project CI dependencies [triggered via API][triggers], particularly for micro-services, but also for complicated build dependencies: e.g. api -> front-end, ce/ee -> omnibus.
-Builds are individual runs of [jobs]. Not to be confused with a `build` job or
-`build` stage.
+## Development workflows
+
+Pipelines accommodate several development workflows:
+
+1. **Branch Flow** (e.g. different branch for dev, qa, staging, production)
+2. **Trunk-based Flow** (e.g. feature branches and single master branch, possibly with tags for releases)
+3. **Fork-based Flow** (e.g. merge requests come from forks)
+
+Example continuous delivery flow:
+
+![CD Flow](img/pipelines-goal.svg)
+
+## Jobs
+
+Jobs can be defined in the [`.gitlab-ci.yml`][jobs-yaml] file. Not to be
+confused with a `build` job or `build` stage.
## Defining pipelines
Pipelines are defined in `.gitlab-ci.yml` by specifying [jobs] that run in
[stages].
-See full [documentation](yaml/README.md#jobs).
+See the reference [documentation for jobs](yaml/README.md#jobs).
## Seeing pipeline status
-You can find the current and historical pipeline runs under **Pipelines** for your
-project.
+You can find the current and historical pipeline runs under your project's
+**Pipelines** tab. Clicking on a pipeline will show the jobs that were run for
+that pipeline.
-## Seeing build status
+![Pipelines index page](img/pipelines_index.png)
-Clicking on a pipeline will show the builds that were run for that pipeline.
+## Seeing job status
-## Badges
+When you visit a single pipeline you can see the related jobs for that pipeline.
+Clicking on an individual job will show you its job trace, and allow you to
+cancel the job, retry it, or erase the job trace.
-There are build status and test coverage report badges available.
+![Pipelines example](img/pipelines.png)
-Go to pipeline settings to see available badges and code you can use to embed
-badges in the `README.md` or your website.
+## Pipeline graphs
-### Build status badge
+> [Introduced][ce-5742] in GitLab 8.11.
-You can access a build status badge image using following link:
+Pipelines can be complex structures with many sequential and parallel jobs.
+To make it a little easier to see what is going on, you can view a graph
+of a single pipeline and its status.
-```
-http://example.gitlab.com/namespace/project/badges/branch/build.svg
-```
+A pipeline graph can be shown in two different ways depending on what page you
+are on.
+
+---
+
+The regular pipeline graph that shows the names of the jobs of each stage can
+be found when you are on a [single pipeline page](#seeing-pipeline-status).
+
+![Pipelines example](img/pipelines.png)
+
+Then, there is the pipeline mini graph which takes less space and can give you a
+quick glance if all jobs pass or something failed. The pipeline mini graph can
+be found when you visit:
+
+- the pipelines index page
+- a single commit page
+- a merge request page
-### Test coverage report badge
+That way, you can see all related jobs for a single commit and the net result
+of each stage of your pipeline. This allows you to quickly see what failed and
+fix it. Stages in pipeline mini graphs are collapsible. Hover your mouse over
+them and click to expand their jobs.
-GitLab makes it possible to define the regular expression for coverage report,
-that each build log will be matched against. This means that each build in the
-pipeline can have the test coverage percentage value defined.
+| **Mini graph** | **Mini graph expanded** |
+| :------------: | :---------------------: |
+| ![Pipelines mini graph](img/pipelines_mini_graph_simple.png) | ![Pipelines mini graph extended](img/pipelines_mini_graph.png) |
-You can access test coverage badge using following link:
+### Grouping similar jobs in the pipeline graph
+
+> [Introduced][ce-6242] in GitLab 8.12.
+
+If you have many similar jobs, your pipeline graph becomes very long and hard
+to read. For that reason, similar jobs can automatically be grouped together.
+If the job names are formatted in certain ways, they will be collapsed into
+a single group in regular pipeline graphs (not the mini graphs).
+You'll know when a pipeline has grouped jobs if you don't see the retry or
+cancel button inside them. Hovering over them will show the number of grouped
+jobs. Click to expand them.
+
+![Grouped pipelines](img/pipelines_grouped.png)
+
+The basic requirements is that there are two numbers separated with one of
+the following (you can even use them interchangeably):
+
+- a space
+- a backslash (`/`)
+- a colon (`:`)
+
+>**Note:**
+More specifically, [it uses][regexp] this regular expression: `\d+[\s:\/\\]+\d+\s*`.
+
+The jobs will be ordered by comparing those two numbers from left to right. You
+usually want the first to be the index and the second the total.
+
+For example, the following jobs will be grouped under a job named `test`:
+
+- `test 0 3` => `test`
+- `test 1 3` => `test`
+- `test 2 3` => `test`
+
+The following jobs will be grouped under a job named `test ruby`:
+
+- `test 1:2 ruby` => `test ruby`
+- `test 2:2 ruby` => `test ruby`
+
+The following jobs will be grouped under a job named `test ruby` as well:
+
+- `1/3 test ruby` => `test ruby`
+- `2/3 test ruby` => `test ruby`
+- `3/3 test ruby` => `test ruby`
+
+### Manual actions from the pipeline graph
+
+> [Introduced][ce-7931] in GitLab 8.15.
+
+[Manual actions][manual] allow you to require manual interaction before moving
+forward with a particular job in CI. Your entire pipeline can run automatically,
+but the actual [deploy to production][env-manual] will require a click.
+
+You can do this straight from the pipeline graph. Just click on the play button
+to execute that particular job. For example, in the image below, the `production`
+stage has a job with a manual action.
+
+![Pipelines example](img/pipelines.png)
+
+### Ordering of jobs in pipeline graphs
+
+**Regular pipeline graph**
+
+In the single pipeline page, jobs are sorted by name.
+
+**Mini pipeline graph**
+
+> [Introduced][ce-9760] in GitLab 9.0.
+
+In the pipeline mini graphs, the jobs are sorted first by severity and then
+by name. The order of severity is:
+
+- failed
+- warning
+- pending
+- running
+- manual
+- canceled
+- success
+- skipped
+- created
+
+![Pipeline mini graph sorting](img/pipelines_mini_graph_sorting.png)
+
+## How the pipeline duration is calculated
+
+Total running time for a given pipeline would exclude retries and pending
+(queue) time. We could reduce this problem down to finding the union of
+periods.
+
+So each job would be represented as a `Period`, which consists of
+`Period#first` as when the job started and `Period#last` as when the
+job was finished. A simple example here would be:
+
+* A (1, 3)
+* B (2, 4)
+* C (6, 7)
+
+Here A begins from 1, and ends to 3. B begins from 2, and ends to 4.
+C begins from 6, and ends to 7. Visually it could be viewed as:
```
-http://example.gitlab.com/namespace/project/badges/branch/coverage.svg
+0 1 2 3 4 5 6 7
+ AAAAAAA
+ BBBBBBB
+ CCCC
```
-If you would like to get the coverage report from the specific job, you can add
-a `job=coverage_job_name` parameter to the URL. For example, it is possible to
-use following Markdown code to embed the est coverage report into `README.md`:
+The union of A, B, and C would be (1, 4) and (6, 7), therefore the
+total running time should be:
-```markdown
-![coverage](http://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg?job=coverage)
```
+(4 - 1) + (7 - 6) => 4
+```
+
+## Badges
-The latest successful pipeline will be used to read the test coverage value.
+Pipeline status and test coverage report badges are available. You can find their
+respective link in the [Pipelines settings] page.
-[builds]: #builds
-[jobs]: yaml/README.md#jobs
+[jobs]: #jobs
+[jobs-yaml]: yaml/README.md#jobs
+[manual]: yaml/README.md#manual
+[env-manual]: environments.md#manually-deploying-to-environments
[stages]: yaml/README.md#stages
-[runners]: runners/README.md
+[runners]: runners/README.html
+[pipelines settings]: ../user/project/pipelines/settings.md
+[triggers]: triggers/README.md
+[ce-5742]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5742
+[ce-6242]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6242
+[ce-7931]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7931
+[ce-9760]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9760
+[regexp]: https://gitlab.com/gitlab-org/gitlab-ce/blob/2f3dc314f42dbd79813e6251792853bc231e69dd/app/models/commit_status.rb#L99
diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md
index c40cdd55ea5..88e53ff40e8 100644
--- a/doc/ci/quick_start/README.md
+++ b/doc/ci/quick_start/README.md
@@ -1,4 +1,4 @@
-# Quick Start
+# Getting started with GitLab CI
>**Note:** Starting from version 8.0, GitLab [Continuous Integration][ci] (CI)
is fully integrated into GitLab itself and is [enabled] by default on all
@@ -6,16 +6,16 @@ projects.
GitLab offers a [continuous integration][ci] service. If you
[add a `.gitlab-ci.yml` file][yaml] to the root directory of your repository,
-and configure your GitLab project to use a [Runner], then each merge request or
-push triggers your CI [pipeline].
+and configure your GitLab project to use a [Runner], then each commit or
+push, triggers your CI [pipeline].
The `.gitlab-ci.yml` file tells the GitLab runner what to do. By default it runs
a pipeline with three [stages]: `build`, `test`, and `deploy`. You don't need to
use all three stages; stages with no jobs are simply ignored.
If everything runs OK (no non-zero return values), you'll get a nice green
-checkmark associated with the pushed commit or merge request. This makes it
-easy to see whether a merge request caused any of the tests to fail before
+checkmark associated with the commit. This makes it
+easy to see whether a commit caused any of the tests to fail before
you even look at the code.
Most projects use GitLab's CI service to run the test suite so that
@@ -31,13 +31,13 @@ So in brief, the steps needed to have a working CI can be summed up to:
From there on, on every push to your Git repository, the Runner will
automagically start the pipeline and the pipeline will appear under the
-project's `/pipelines` page.
+project's **Pipelines** page.
---
This guide assumes that you:
-- have a working GitLab instance of version 8.0 or higher or are using
+- have a working GitLab instance of version 8.0+r or are using
[GitLab.com](https://gitlab.com)
- have a project in GitLab that you would like to use CI for
@@ -54,7 +54,7 @@ The `.gitlab-ci.yml` file is where you configure what CI does with your project.
It lives in the root of your repository.
On any push to your repository, GitLab will look for the `.gitlab-ci.yml`
-file and start builds on _Runners_ according to the contents of the file,
+file and start jobs on _Runners_ according to the contents of the file,
for that commit.
Because `.gitlab-ci.yml` is in the repository and is version controlled, old
@@ -63,11 +63,12 @@ have different pipelines and jobs, and you have a single source of truth for CI.
You can read more about the reasons why we are using `.gitlab-ci.yml` [in our
blog about it][blog-ci].
-**Note:** `.gitlab-ci.yml` is a [YAML](https://en.wikipedia.org/wiki/YAML) file
-so you have to pay extra attention to indentation. Always use spaces, not tabs.
-
### Creating a simple `.gitlab-ci.yml` file
+>**Note:**
+`.gitlab-ci.yml` is a [YAML](https://en.wikipedia.org/wiki/YAML) file
+so you have to pay extra attention to indentation. Always use spaces, not tabs.
+
You need to create a file named `.gitlab-ci.yml` in the root directory of your
repository. Below is an example for a Ruby on Rails project.
@@ -88,7 +89,7 @@ rubocop:
- bundle exec rubocop
```
-This is the simplest possible build configuration that will work for most Ruby
+This is the simplest possible configuration that will work for most Ruby
applications:
1. Define two jobs `rspec` and `rubocop` (the names are arbitrary) with
@@ -98,22 +99,22 @@ applications:
The `.gitlab-ci.yml` file defines sets of jobs with constraints of how and when
they should be run. The jobs are defined as top-level elements with a name (in
our case `rspec` and `rubocop`) and always have to contain the `script` keyword.
-Jobs are used to create builds, which are then picked by
+Jobs are used to create jobs, which are then picked by
[Runners](../runners/README.md) and executed within the environment of the Runner.
What is important is that each job is run independently from each other.
If you want to check whether your `.gitlab-ci.yml` file is valid, there is a
Lint tool under the page `/ci/lint` of your GitLab instance. You can also find
-a "CI Lint" button to go to this page under **Pipelines > Pipelines** and
-**Pipelines > Builds** in your project.
+a "CI Lint" button to go to this page under **Pipelines ➔ Pipelines** and
+**Pipelines ➔ Jobs** in your project.
For more information and a complete `.gitlab-ci.yml` syntax, please read
-[the documentation on .gitlab-ci.yml](../yaml/README.md).
+[the reference documentation on .gitlab-ci.yml](../yaml/README.md).
### Push `.gitlab-ci.yml` to GitLab
-Once you've created `.gitlab-ci.yml`, you should add it to your git repository
+Once you've created `.gitlab-ci.yml`, you should add it to your Git repository
and push it to GitLab.
```bash
@@ -125,28 +126,27 @@ git push origin master
Now if you go to the **Pipelines** page you will see that the pipeline is
pending.
-You can also go to the **Commits** page and notice the little clock icon next
+You can also go to the **Commits** page and notice the little pause icon next
to the commit SHA.
![New commit pending](img/new_commit.png)
-Clicking on the clock icon you will be directed to the builds page for that
-specific commit.
+Clicking on it you will be directed to the jobs page for that specific commit.
-![Single commit builds page](img/single_commit_status_pending.png)
+![Single commit jobs page](img/single_commit_status_pending.png)
Notice that there are two jobs pending which are named after what we wrote in
`.gitlab-ci.yml`. The red triangle indicates that there is no Runner configured
-yet for these builds.
+yet for these jobs.
-The next step is to configure a Runner so that it picks the pending builds.
+The next step is to configure a Runner so that it picks the pending jobs.
## Configuring a Runner
-In GitLab, Runners run the builds that you define in `.gitlab-ci.yml`. A Runner
+In GitLab, Runners run the jobs that you define in `.gitlab-ci.yml`. A Runner
can be a virtual machine, a VPS, a bare-metal machine, a docker container or
even a cluster of containers. GitLab and the Runners communicate through an API,
-so the only requirement is that the Runner's machine has Internet access.
+so the only requirement is that the Runner's machine has [Internet] access.
A Runner can be specific to a certain project or serve multiple projects in
GitLab. If it serves all projects it's called a _Shared Runner_.
@@ -155,9 +155,9 @@ Find more information about different Runners in the
[Runners](../runners/README.md) documentation.
You can find whether any Runners are assigned to your project by going to
-**Settings > Runners**. Setting up a Runner is easy and straightforward. The
-official Runner supported by GitLab is written in Go and can be found at
-<https://gitlab.com/gitlab-org/gitlab-ci-multi-runner>.
+**Settings ➔ Pipelines**. Setting up a Runner is easy and straightforward. The
+official Runner supported by GitLab is written in Go and its documentation
+can be found at <https://docs.gitlab.com/runner/>.
In order to have a functional Runner you need to follow two steps:
@@ -167,28 +167,25 @@ In order to have a functional Runner you need to follow two steps:
Follow the links above to set up your own Runner or use a Shared Runner as
described in the next section.
-For other types of unofficial Runners written in other languages, see the
-[instructions for the various GitLab Runners](https://about.gitlab.com/gitlab-ci/#gitlab-runner).
-
Once the Runner has been set up, you should see it on the Runners page of your
-project, following **Settings > Runners**.
+project, following **Settings ➔ Pipelines**.
![Activated runners](img/runners_activated.png)
### Shared Runners
-If you use [GitLab.com](https://gitlab.com/) you can use **Shared Runners**
+If you use [GitLab.com](https://gitlab.com/) you can use the **Shared Runners**
provided by GitLab Inc.
These are special virtual machines that run on GitLab's infrastructure and can
build any project.
-To enable **Shared Runners** you have to go to your project's
-**Settings > Runners** and click **Enable shared runners**.
+To enable the **Shared Runners** you have to go to your project's
+**Settings ➔ Pipelines** and click **Enable shared runners**.
[Read more on Shared Runners](../runners/README.md).
-## Seeing the status of your pipeline and builds
+## Seeing the status of your pipeline and jobs
After configuring the Runner successfully, you should see the status of your
last commit change from _pending_ to either _running_, _success_ or _failed_.
@@ -197,36 +194,25 @@ You can view all pipelines by going to the **Pipelines** page in your project.
![Commit status](img/pipelines_status.png)
-Or you can view all builds, by going to the **Pipelines > Builds** page.
+Or you can view all jobs, by going to the **Pipelines ➔ Jobs** page.
![Commit status](img/builds_status.png)
-By clicking on a Build ID, you will be able to see the log of that build.
-This is important to diagnose why a build failed or acted differently than
+By clicking on a job's status, you will be able to see the log of that job.
+This is important to diagnose why a job failed or acted differently than
you expected.
![Build log](img/build_log.png)
You are also able to view the status of any commit in the various pages in
-GitLab, such as **Commits** and **Merge Requests**.
-
-## Enabling build emails
-
-If you want to receive e-mail notifications about the result status of the
-builds, you should explicitly enable the **Builds Emails** service under your
-project's settings.
-
-For more information read the
-[Builds emails service documentation](../../project_services/builds_emails.md).
+GitLab, such as **Commits** and **Merge requests**.
## Examples
Visit the [examples README][examples] to see a list of examples using GitLab
CI with various languages.
-Awesome! You started using CI in GitLab!
-
-[runner-install]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/tree/master#install-gitlab-runner
+[runner-install]: https://docs.gitlab.com/runner/install/
[blog-ci]: https://about.gitlab.com/2015/05/06/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml/
[examples]: ../examples/README.md
[ci]: https://about.gitlab.com/gitlab-ci/
@@ -235,3 +221,4 @@ Awesome! You started using CI in GitLab!
[enabled]: ../enable_or_disable_ci.md
[stages]: ../yaml/README.md#stages
[pipeline]: ../pipelines.md
+[internet]: https://about.gitlab.com/images/theinternet.png
diff --git a/doc/ci/quick_start/img/build_log.png b/doc/ci/quick_start/img/build_log.png
index b53a6cd86b0..3a7248ca772 100644
--- a/doc/ci/quick_start/img/build_log.png
+++ b/doc/ci/quick_start/img/build_log.png
Binary files differ
diff --git a/doc/ci/quick_start/img/builds_status.png b/doc/ci/quick_start/img/builds_status.png
index 47862761ffe..f829240f3b3 100644
--- a/doc/ci/quick_start/img/builds_status.png
+++ b/doc/ci/quick_start/img/builds_status.png
Binary files differ
diff --git a/doc/ci/quick_start/img/new_commit.png b/doc/ci/quick_start/img/new_commit.png
index a53562ce328..b3dd848b294 100644
--- a/doc/ci/quick_start/img/new_commit.png
+++ b/doc/ci/quick_start/img/new_commit.png
Binary files differ
diff --git a/doc/ci/quick_start/img/pipelines_status.png b/doc/ci/quick_start/img/pipelines_status.png
index 6bc97bb739c..06d1559f5d2 100644
--- a/doc/ci/quick_start/img/pipelines_status.png
+++ b/doc/ci/quick_start/img/pipelines_status.png
Binary files differ
diff --git a/doc/ci/quick_start/img/runners_activated.png b/doc/ci/quick_start/img/runners_activated.png
index 23261123b18..cd83c1a7e4c 100644
--- a/doc/ci/quick_start/img/runners_activated.png
+++ b/doc/ci/quick_start/img/runners_activated.png
Binary files differ
diff --git a/doc/ci/quick_start/img/single_commit_status_pending.png b/doc/ci/quick_start/img/single_commit_status_pending.png
index ccf3ac957bb..ffc7054d3b0 100644
--- a/doc/ci/quick_start/img/single_commit_status_pending.png
+++ b/doc/ci/quick_start/img/single_commit_status_pending.png
Binary files differ
diff --git a/doc/ci/quick_start/img/status_pending.png b/doc/ci/quick_start/img/status_pending.png
deleted file mode 100644
index 9feacf0c961..00000000000
--- a/doc/ci/quick_start/img/status_pending.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/review_apps/img/review_apps_preview_in_mr.png b/doc/ci/review_apps/img/review_apps_preview_in_mr.png
new file mode 100644
index 00000000000..0300392f24b
--- /dev/null
+++ b/doc/ci/review_apps/img/review_apps_preview_in_mr.png
Binary files differ
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
new file mode 100644
index 00000000000..28c484ddbe6
--- /dev/null
+++ b/doc/ci/review_apps/index.md
@@ -0,0 +1,124 @@
+# Getting started with Review Apps
+
+>
+- [Introduced][ce-21971] in GitLab 8.12. Further additions were made in GitLab
+ 8.13 and 8.14.
+- Inspired by [Heroku's Review Apps][heroku-apps] which itself was inspired by
+ [Fourchette].
+
+The basis of Review Apps is the [dynamic environments] which allow you to create
+a new environment (dynamically) for each one of your branches.
+
+A Review App can then be visible as a link when you visit the [merge request]
+relevant to the branch. That way, you are able to see live all changes introduced
+by the merge request changes. Reviewing anything, from performance to interface
+changes, becomes much easier with a live environment and as such, Review Apps
+can make a huge impact on your development flow.
+
+They mostly make sense to be used with web applications, but you can use them
+any way you'd like.
+
+## Overview
+
+Simply put, a Review App is a mapping of a branch with an environment as there
+is a 1:1 relation between them.
+
+Here's an example of what it looks like when viewing a merge request with a
+dynamically set environment.
+
+![Review App in merge request](img/review_apps_preview_in_mr.png)
+
+In the image above you can see that the `add-new-line` branch was successfully
+built and deployed under a dynamic environment and can be previewed with an
+also dynamically URL.
+
+The details of the Review Apps implementation depend widely on your real
+technology stack and on your deployment process. The simplest case is to
+deploy a simple static HTML website, but it will not be that straightforward
+when your app is using a database for example. To make a branch be deployed
+on a temporary instance and booting up this instance with all required software
+and services automatically on the fly is not a trivial task. However, it is
+doable, especially if you use Docker, or at least a configuration management
+tool like Chef, Puppet, Ansible or Salt.
+
+## Prerequisites
+
+To get a better understanding of Review Apps, you must first learn how
+environments and deployments work. The following docs will help you grasp that
+knowledge:
+
+1. First, learn about [environments][] and their role in the development workflow.
+1. Then make a small stop to learn about [CI variables][variables] and how they
+ can be used in your CI jobs.
+1. Next, explore the [`environment` syntax][yaml-env] as defined in `.gitlab-ci.yml`.
+ This will be your primary reference when you are finally comfortable with
+ how environments work.
+1. Additionally, find out about [manual actions][] and how you can use them to
+ deploy to critical environments like production with the push of a button.
+1. And as a last step, follow the [example tutorials](#examples) which will
+ guide you step by step to set up the infrastructure and make use of
+ Review Apps.
+
+## Configuration
+
+The configuration of Review apps depends on your technology stack and your
+infrastructure. Read the [dynamic environments] documentation to understand
+how to define and create them.
+
+## Creating and destroying Review Apps
+
+The creation and destruction of a Review App is defined in `.gitlab-ci.yml`
+at a job level under the `environment` keyword.
+
+Check the [environments] documentation how to do so.
+
+## A simple workflow
+
+The process of adding Review Apps in your workflow would look like:
+
+1. Set up the infrastructure to host and deploy the Review Apps.
+1. [Install][install-runner] and [configure][conf-runner] a Runner that does
+ the deployment.
+1. Set up a job in `.gitlab-ci.yml` that uses the predefined
+ [predefined CI environment variable][variables] `${CI_COMMIT_REF_NAME}` to
+ create dynamic environments and restrict it to run only on branches.
+1. Optionally set a job that [manually stops][manual-env] the Review Apps.
+
+From there on, you would follow the branched Git flow:
+
+1. Push a branch and let the Runner deploy the Review App based on the `script`
+ definition of the dynamic environment job.
+1. Wait for the Runner to build and/or deploy your web app.
+1. Click on the link that's present in the MR related to the branch and see the
+ changes live.
+
+## Limitations
+
+Check the [environments limitations](../environments.md#limitations).
+
+## Examples
+
+A list of examples used with Review Apps can be found below:
+
+- [Use with NGINX][app-nginx] - Use NGINX and the shell executor of GitLab Runner
+ to deploy a simple HTML website.
+
+And below is a soon to be added examples list:
+
+- Use with Amazon S3
+- Use on Heroku with dpl
+- Use with OpenShift/kubernetes
+
+[app-nginx]: https://gitlab.com/gitlab-examples/review-apps-nginx
+[ce-21971]: https://gitlab.com/gitlab-org/gitlab-ce/issues/21971
+[dynamic environments]: ../environments.md#dynamic-environments
+[environments]: ../environments.md
+[fourchette]: https://github.com/rainforestapp/fourchette
+[heroku-apps]: https://devcenter.heroku.com/articles/github-integration-review-apps
+[manual actions]: ../environments.md#manual-actions
+[merge request]: ../../user/project/merge_requests.md
+[variables]: ../variables/README.md
+[yaml-env]: ../yaml/README.md#environment
+[install-runner]: https://docs.gitlab.com/runner/install/
+[conf-runner]: https://docs.gitlab.com/runner/commands/
+[manual-env]: ../environments.md#stopping-an-environment
diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md
index ddebd987650..76d746155eb 100644
--- a/doc/ci/runners/README.md
+++ b/doc/ci/runners/README.md
@@ -1,162 +1,220 @@
# Runners
-In GitLab CI, Runners run your [yaml](../yaml/README.md).
-A runner is an isolated (virtual) machine that picks up builds
-through the coordinator API of GitLab CI.
+In GitLab CI, Runners run the code defined in [`.gitlab-ci.yml`](../yaml/README.md).
+They are isolated (virtual) machines that pick up jobs through the coordinator
+API of GitLab CI.
-A runner can be specific to a certain project or serve any project
-in GitLab CI. A runner that serves all projects is called a shared runner.
+A Runner can be specific to a certain project or serve any project
+in GitLab CI. A Runner that serves all projects is called a shared Runner.
-Ideally, GitLab Runner should not be installed on the same machine as GitLab.
+Ideally, the GitLab Runner should not be installed on the same machine as GitLab.
Read the [requirements documentation](../../install/requirements.md#gitlab-runner)
for more information.
-## Shared vs. Specific Runners
+## Shared vs specific Runners
-A runner that is specific only runs for the specified project. A shared runner
-can run jobs for every project that has enabled the option
-`Allow shared runners`.
+After [installing the Runner][install], you can either register it as shared or
+specific. You can only register a shared Runner if you have admin access to
+the GitLab instance. The main differences between a shared and a specific Runner
+are:
-**Shared runners** are useful for jobs that have similar requirements,
-between multiple projects. Rather than having multiple runners idling for
-many projects, you can have a single or a small number of runners that handle
-multiple projects. This makes it easier to maintain and update runners.
+- **Shared Runners** are useful for jobs that have similar requirements,
+ between multiple projects. Rather than having multiple Runners idling for
+ many projects, you can have a single or a small number of Runners that handle
+ multiple projects. This makes it easier to maintain and update them.
+ Shared Runners process jobs using a [fair usage queue](#how-shared-runners-pick-jobs).
+ In contrast to specific Runners that use a FIFO queue, this prevents
+ cases where projects create hundreds of jobs which can lead to eating all
+ available shared Runners resources.
+- **Specific Runners** are useful for jobs that have special requirements or for
+ projects with a specific demand. If a job has certain requirements, you can set
+ up the specific Runner with this in mind, while not having to do this for all
+ Runners. For example, if you want to deploy a certain project, you can setup
+ a specific Runner to have the right credentials for this. The [usage of tags](#using-tags)
+ may be useful in this case. Specific Runners process jobs using a [FIFO] queue.
-**Specific runners** are useful for jobs that have special requirements or for
-projects with a specific demand. If a job has certain requirements, you can set
-up the specific runner with this in mind, while not having to do this for all
-runners. For example, if you want to deploy a certain project, you can setup
-a specific runner to have the right credentials for this.
+A Runner that is specific only runs for the specified project(s). A shared Runner
+can run jobs for every project that has enabled the option **Allow shared Runners**
+under **Settings ➔ Pipelines**.
-Projects with high demand of CI activity can also benefit from using specific runners.
-By having dedicated runners you are guaranteed that the runner is not being held
-up by another project's jobs.
+Projects with high demand of CI activity can also benefit from using specific
+Runners. By having dedicated Runners you are guaranteed that the Runner is not
+being held up by another project's jobs.
-You can set up a specific runner to be used by multiple projects. The difference
-with a shared runner is that you have to enable each project explicitly for
-the runner to be able to run its jobs.
+You can set up a specific Runner to be used by multiple projects. The difference
+with a shared Runner is that you have to enable each project explicitly for
+the Runner to be able to run its jobs.
-Specific runners do not get shared with forked projects automatically.
-A fork does copy the CI settings (jobs, allow shared, etc) of the cloned repository.
+Specific Runners do not get shared with forked projects automatically.
+A fork does copy the CI settings (jobs, allow shared, etc) of the cloned
+repository.
-# Creating and Registering a Runner
+## Registering a shared Runner
-There are several ways to create a runner. Only after creation, upon
-registration its status as Shared or Specific is determined.
+You can only register a shared Runner if you are an admin of the GitLab instance.
-[See the documentation for](https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/#installation)
-the different methods of installing a Runner instance.
+1. Grab the shared-Runner token on the `admin/runners` page
-After installing the runner, you can either register it as `Shared` or as `Specific`.
-You can only register a Shared Runner if you have admin access to the GitLab instance.
+ ![Shared Runners admin area](img/shared_runners_admin.png)
-## Registering a Shared Runner
+1. [Register the Runner][register]
-You can only register a shared runner if you are an admin on the linked
-GitLab instance.
+Shared Runners are enabled by default as of GitLab 8.2, but can be disabled
+with the **Disable shared Runners** button which is present under each project's
+**Settings ➔ Pipelines** page. Previous versions of GitLab defaulted shared
+Runners to disabled.
-Grab the shared-runner token on the `admin/runners` page of your GitLab CI
-instance.
+## Registering a specific Runner
-![shared token](shared_runner.png)
+Registering a specific can be done in two ways:
-Now simply register the runner as any runner:
+1. Creating a Runner with the project registration token
+1. Converting a shared Runner into a specific Runner (one-way, admin only)
-```
-sudo gitlab-ci-multi-runner register
-```
+### Registering a specific Runner with a project registration token
-Shared runners are enabled by default as of GitLab 8.2, but can be disabled with the
-`DISABLE SHARED RUNNERS` button. Previous versions of GitLab defaulted shared runners to
-disabled.
+To create a specific Runner without having admin rights to the GitLab instance,
+visit the project you want to make the Runner work for in GitLab:
-## Registering a Specific Runner
+1. Go to **Settings ➔ Pipelines** to obtain the token
+1. [Register the Runner][register]
-Registering a specific can be done in two ways:
+### Making an existing shared Runner specific
+
+If you are an admin on your GitLab instance, you can turn any shared Runner into
+a specific one, but not the other way around. Keep in mind that this is a one
+way transition.
+
+1. Go to the Runners in the admin area **Overview ➔ Runners** (`/admin/runners`)
+ and find your Runner
+1. Enable any projects under **Restrict projects for this Runner** to be used
+ with the Runner
+
+From now on, the shared Runner will be specific to those projects.
+
+## Locking a specific Runner from being enabled for other projects
-1. Creating a runner with the project registration token
-1. Converting a shared runner into a specific runner (one-way, admin only)
+You can configure a Runner to assign it exclusively to a project. When a
+Runner is locked this way, it can no longer be enabled for other projects.
+This setting can be enabled the first time you [register a Runner][register] and
+can be changed afterwards under each Runner's settings.
-There are several ways to create a runner instance. The steps below only
-concern registering the runner on GitLab CI.
+To lock/unlock a Runner:
-### Registering a Specific Runner with a Project Registration token
+1. Visit your project's **Settings ➔ Pipelines**
+1. Find the Runner you wish to lock/unlock and make sure it's enabled
+1. Click the pencil button
+1. Check the **Lock to current projects** option
+1. Click **Save changes** for the changes to take effect
-To create a specific runner without having admin rights to the GitLab instance,
-visit the project you want to make the runner work for in GitLab CI.
+## How shared Runners pick jobs
-Click on the runner tab and use the registration token you find there to
-setup a specific runner for this project.
+Shared Runners abide to a process queue we call fair usage. The fair usage
+algorithm tries to assign jobs to shared Runners from projects that have the
+lowest number of jobs currently running on shared Runners.
-![project runners in GitLab CI](project_specific.png)
+**Example 1**
-To register the runner, run the command below and follow instructions:
+We have following jobs in queue:
-```
-sudo gitlab-ci-multi-runner register
-```
+- Job 1 for Project 1
+- Job 2 for Project 1
+- Job 3 for Project 1
+- Job 4 for Project 2
+- Job 5 for Project 2
+- Job 6 for Project 3
-### Lock a specific runner from being enabled for other projects
+With the fair usage algorithm jobs are assigned in following order:
-You can configure a runner to assign it exclusively to a project. When a
-runner is locked this way, it can no longer be enabled for other projects.
-This setting is available on each runner in *Project Settings* > *Runners*.
+1. Job 1 is chosen first, because it has the lowest job number from projects with no running jobs (i.e. all projects)
+1. Job 4 is next, because 4 is now the lowest job number from projects with no running jobs (Project 1 has a job running)
+1. Job 6 is next, because 6 is now the lowest job number from projects with no running jobs (Projects 1 and 2 have jobs running)
+1. Job 2 is next, because, of projects with the lowest number of jobs running (each has 1), it is the lowest job number
+1. Job 5 is next, because Project 1 now has 2 jobs running, and between Projects 2 and 3, Job 5 is the lowest remaining job number
+1. Lastly we choose Job 3... because it's the only job left
-### Making an existing Shared Runner Specific
+---
-If you are an admin on your GitLab instance,
-you can make any shared runner a specific runner, _but you can not
-make a specific runner a shared runner_.
+**Example 2**
-To make a shared runner specific, go to the runner page (`/admin/runners`)
-and find your runner. Add any projects on the left to make this runner
-run exclusively for these projects, therefore making it a specific runner.
+We have following jobs in queue:
-![making a shared runner specific](shared_to_specific_admin.png)
+- Job 1 for project 1
+- Job 2 for project 1
+- Job 3 for project 1
+- Job 4 for project 2
+- Job 5 for project 2
+- Job 6 for project 3
-## Using Shared Runners Effectively
+With the fair usage algorithm jobs are assigned in following order:
-If you are planning to use shared runners, there are several things you
+1. Job 1 is chosen first, because it has the lowest job number from projects with no running jobs (i.e. all projects)
+1. We finish job 1
+1. Job 2 is next, because, having finished Job 1, all projects have 0 jobs running again, and 2 is the lowest available job number
+1. Job 4 is next, because with Project 1 running a job, 4 is the lowest number from projects running no jobs (Projects 2 and 3)
+1. We finish job 4
+1. Job 5 is next, because having finished Job 4, Project 2 has no jobs running again
+1. Job 6 is next, because Project 3 is the only project left with no running jobs
+1. Lastly we choose Job 3... because, again, it's the only job left (who says 1 is the loneliest number?)
+
+## Using shared Runners effectively
+
+If you are planning to use shared Runners, there are several things you
should keep in mind.
-### Use Tags
+### Using tags
-You must setup a runner to be able to run all the different types of jobs
+You must setup a Runner to be able to run all the different types of jobs
that it may encounter on the projects it's shared over. This would be
problematic for large amounts of projects, if it wasn't for tags.
By tagging a Runner for the types of jobs it can handle, you can make sure
-shared runners will only run the jobs they are equipped to run.
+shared Runners will only run the jobs they are equipped to run.
-For instance, at GitLab we have runners tagged with "rails" if they contain
+For instance, at GitLab we have Runners tagged with "rails" if they contain
the appropriate dependencies to run Rails test suites.
-### Prevent runner with tags from picking jobs without tags
+### Preventing Runners with tags from picking jobs without tags
+
+You can configure a Runner to prevent it from picking jobs with tags when
+the Runner does not have tags assigned. This setting can be enabled the first
+time you [register a Runner][register] and can be changed afterwards under
+each Runner's settings.
-You can configure a runner to prevent it from picking jobs with tags when
-the runner does not have tags assigned. This setting is available on each
-runner in *Project Settings* > *Runners*.
+To make a Runner pick tagged/untagged jobs:
+
+1. Visit your project's **Settings ➔ Pipelines**
+1. Find the Runner you wish and make sure it's enabled
+1. Click the pencil button
+1. Check the **Run untagged jobs** option
+1. Click **Save changes** for the changes to take effect
### Be careful with sensitive information
-If you can run a build on a runner, you can get access to any code it runs
-and get the token of the runner. With shared runners, this means that anyone
-that runs jobs on the runner, can access anyone else's code that runs on the runner.
+If you can run a job on a Runner, you can get access to any code it runs
+and get the token of the Runner. With shared Runners, this means that anyone
+that runs jobs on the Runner, can access anyone else's code that runs on the
+Runner.
-In addition, because you can get access to the runner token, it is possible
-to create a clone of a runner and submit false builds, for example.
+In addition, because you can get access to the Runner token, it is possible
+to create a clone of a Runner and submit false jobs, for example.
-The above is easily avoided by restricting the usage of shared runners
+The above is easily avoided by restricting the usage of shared Runners
on large public GitLab instances and controlling access to your GitLab instance.
### Forks
Whenever a project is forked, it copies the settings of the jobs that relate
-to it. This means that if you have shared runners setup for a project and
-someone forks that project, the shared runners will also serve jobs of this
+to it. This means that if you have shared Runners setup for a project and
+someone forks that project, the shared Runners will also serve jobs of this
project.
## Attack vectors in Runners
-Mentioned briefly earlier, but the following things of runners can be exploited.
-We're always looking for contributions that can mitigate these [Security Considerations](https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/security/index.md).
+Mentioned briefly earlier, but the following things of Runners can be exploited.
+We're always looking for contributions that can mitigate these
+[Security Considerations](https://docs.gitlab.com/runner/security/).
+
+[install]: http://docs.gitlab.com/runner/install/
+[fifo]: https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics)
+[register]: http://docs.gitlab.com/runner/register/
diff --git a/doc/ci/runners/img/shared_runners_admin.png b/doc/ci/runners/img/shared_runners_admin.png
new file mode 100644
index 00000000000..e049b339b36
--- /dev/null
+++ b/doc/ci/runners/img/shared_runners_admin.png
Binary files differ
diff --git a/doc/ci/runners/project_specific.png b/doc/ci/runners/project_specific.png
deleted file mode 100644
index c812defa67b..00000000000
--- a/doc/ci/runners/project_specific.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/runners/shared_runner.png b/doc/ci/runners/shared_runner.png
deleted file mode 100644
index 31574a17764..00000000000
--- a/doc/ci/runners/shared_runner.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/services/mysql.md b/doc/ci/services/mysql.md
index aaf3aa77837..338368dbbc9 100644
--- a/doc/ci/services/mysql.md
+++ b/doc/ci/services/mysql.md
@@ -31,7 +31,7 @@ Database: el_duderino
```
If you are wondering why we used `mysql` for the `Host`, read more at
-[How is service linked to the build](../docker/using_docker_images.md#how-is-service-linked-to-the-build).
+[How is service linked to the job](../docker/using_docker_images.md#how-is-service-linked-to-the-job).
You can also use any other docker image available on [Docker Hub][hub-mysql].
For example, to use MySQL 5.5 the service becomes `mysql:5.5`.
@@ -112,7 +112,7 @@ convenience that runs on [GitLab.com](https://gitlab.com) using our publicly
available [shared runners](../runners/README.md).
Want to hack on it? Simply fork it, commit and push your changes. Within a few
-moments the changes will be picked by a public runner and the build will begin.
+moments the changes will be picked by a public runner and the job will begin.
[hub-mysql]: https://hub.docker.com/r/_/mysql/
[mysql-example-repo]: https://gitlab.com/gitlab-examples/mysql
diff --git a/doc/ci/services/postgres.md b/doc/ci/services/postgres.md
index f787cc0a124..3899b555f32 100644
--- a/doc/ci/services/postgres.md
+++ b/doc/ci/services/postgres.md
@@ -31,7 +31,7 @@ Database: nice_marmot
```
If you are wondering why we used `postgres` for the `Host`, read more at
-[How is service linked to the build](../docker/using_docker_images.md#how-is-service-linked-to-the-build).
+[How is service linked to the job](../docker/using_docker_images.md#how-is-service-linked-to-the-job).
You can also use any other docker image available on [Docker Hub][hub-pg].
For example, to use PostgreSQL 9.3 the service becomes `postgres:9.3`.
@@ -108,7 +108,7 @@ convenience that runs on [GitLab.com](https://gitlab.com) using our publicly
available [shared runners](../runners/README.md).
Want to hack on it? Simply fork it, commit and push your changes. Within a few
-moments the changes will be picked by a public runner and the build will begin.
+moments the changes will be picked by a public runner and the job will begin.
[hub-pg]: https://hub.docker.com/r/_/postgres/
[postgres-example-repo]: https://gitlab.com/gitlab-examples/postgres
diff --git a/doc/ci/services/redis.md b/doc/ci/services/redis.md
index 80705024d2f..554c321fd0c 100644
--- a/doc/ci/services/redis.md
+++ b/doc/ci/services/redis.md
@@ -63,7 +63,7 @@ that runs on [GitLab.com](https://gitlab.com) using our publicly available
[shared runners](../runners/README.md).
Want to hack on it? Simply fork it, commit and push your changes. Within a few
-moments the changes will be picked by a public runner and the build will begin.
+moments the changes will be picked by a public runner and the job will begin.
[hub-redis]: https://hub.docker.com/r/_/redis/
[redis-example-repo]: https://gitlab.com/gitlab-examples/redis
diff --git a/doc/ci/ssh_keys/README.md b/doc/ci/ssh_keys/README.md
index b858029d25e..befaa06e918 100644
--- a/doc/ci/ssh_keys/README.md
+++ b/doc/ci/ssh_keys/README.md
@@ -25,19 +25,28 @@ This is the universal solution which works with any type of executor
1. Create a new SSH key pair with [ssh-keygen][]
2. Add the private key as a **Secret Variable** to the project
-3. Run the [ssh-agent][] during build to load the private key.
+3. Run the [ssh-agent][] during job to load the private key.
## SSH keys when using the Docker executor
You will first need to create an SSH key pair. For more information, follow the
-instructions to [generate an SSH key](../../ssh/README.md). Do not add a comment
-to the SSH key, or the `before_script` will prompt for a passphrase.
+instructions to [generate an SSH key](../../ssh/README.md). Do not add a
+passphrase to the SSH key, or the `before_script` will prompt for it.
Then, create a new **Secret Variable** in your project settings on GitLab
following **Settings > Variables**. As **Key** add the name `SSH_PRIVATE_KEY`
and in the **Value** field paste the content of your _private_ key that you
created earlier.
+It is also good practice to check the server's own public key to make sure you
+are not being targeted by a man-in-the-middle attack. To do this, add another
+variable named `SSH_SERVER_HOSTKEYS`. To find out the hostkeys of your server, run
+the `ssh-keyscan YOUR_SERVER` command from a trusted network (ideally, from the
+server itself), and paste its output into the `SSH_SERVER_HOSTKEY` variable. If
+you need to connect to multiple servers, concatenate all the server public keys
+that you collected into the **Value** of the variable. There must be one key per
+line.
+
Next you need to modify your `.gitlab-ci.yml` with a `before_script` action.
Add it to the top:
@@ -59,6 +68,11 @@ before_script:
# you will overwrite your user's SSH config.
- mkdir -p ~/.ssh
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
+ # In order to properly check the server's host key, assuming you created the
+ # SSH_SERVER_HOSTKEYS variable previously, uncomment the following two lines
+ # instead.
+ # - mkdir -p ~/.ssh
+ # - '[[ -f /.dockerenv ]] && echo "$SSH_SERVER_HOSTKEYS" > ~/.ssh/known_hosts'
```
As a final step, add the _public_ key from the one you created earlier to the
@@ -77,7 +91,7 @@ SSH key.
You can generate the SSH key from the machine that GitLab Runner is installed
on, and use that key for all projects that are run on this machine.
-First, you need to login to the server that runs your builds.
+First, you need to login to the server that runs your jobs.
Then from the terminal login as the `gitlab-runner` user and generate the SSH
key pair as described in the [SSH keys documentation](../../ssh/README.md).
@@ -103,7 +117,7 @@ that runs on [GitLab.com](https://gitlab.com) using our publicly available
[shared runners](../runners/README.md).
Want to hack on it? Simply fork it, commit and push your changes. Within a few
-moments the changes will be picked by a public runner and the build will begin.
+moments the changes will be picked by a public runner and the job will begin.
[ssh-keygen]: http://linux.die.net/man/1/ssh-keygen
[ssh-agent]: http://linux.die.net/man/1/ssh-agent
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
index 84048f1d25f..7ec7136d8c6 100644
--- a/doc/ci/triggers/README.md
+++ b/doc/ci/triggers/README.md
@@ -1,19 +1,27 @@
-# Triggering Builds through the API
+# Triggering pipelines through the API
-> [Introduced][ci-229] in GitLab CE 7.14.
+> **Notes**:
+- [Introduced][ci-229] in GitLab CE 7.14.
+- GitLab 8.12 has a completely redesigned job permissions system. Read all
+ about the [new model and its implications](../../user/project/new_ci_build_permissions_model.md#job-triggers).
-> **Note**:
-GitLab 8.12 has a completely redesigned build permissions system.
-Read all about the [new model and its implications](../../user/project/new_ci_build_permissions_model.md#build-triggers).
+Triggers can be used to force a pipeline rerun of a specific `ref` (branch or
+tag) with an API call.
+
+## Authentication tokens
+
+The following methods of authentication are supported.
-Triggers can be used to force a rebuild of a specific branch, tag or commit,
-with an API call.
+### Trigger token
-## Add a trigger
+A unique trigger token can be obtained when [adding a new trigger](#adding-a-new-trigger).
-You can add a new trigger by going to your project's **Settings > Triggers**.
-The **Add trigger** button will create a new token which you can then use to
-trigger a rebuild of this particular project.
+## Adding a new trigger
+
+You can add a new trigger by going to your project's
+**Settings ➔ Pipelines** under **Triggers**. The **Add trigger** button will
+create a new token which you can then use to trigger a rerun of this
+particular project's pipeline.
Every new trigger you create, gets assigned a different token which you can
then use inside your scripts or `.gitlab-ci.yml`. You also have a nice
@@ -21,70 +29,66 @@ overview of the time the triggers were last used.
![Triggers page overview](img/triggers_page.png)
-## Revoke a trigger
-
-You can revoke a trigger any time by going at your project's
-**Settings > Triggers** and hitting the **Revoke** button. The action is
-irreversible.
-
-## Trigger a build
-
-To trigger a build you need to send a `POST` request to GitLab's API endpoint:
-
-```
-POST /projects/:id/trigger/builds
-```
-
-The required parameters are the trigger's `token` and the Git `ref` on which
-the trigger will be performed. Valid refs are the branch, the tag or the commit
-SHA. The `:id` of a project can be found by [querying the API](../../api/projects.md)
-or by visiting the **Triggers** page which provides self-explanatory examples.
+## Taking ownership of a trigger
-When a rebuild is triggered, the information is exposed in GitLab's UI under
-the **Builds** page and the builds are marked as `triggered`.
-
-![Marked rebuilds as triggered on builds page](img/builds_page.png)
+> **Note**:
+GitLab 9.0 introduced a trigger ownership to solve permission problems.
----
+Each created trigger when run will impersonate their associated user including
+their access to projects and their project permissions.
-You can see which trigger caused the rebuild by visiting the single build page.
-The token of the trigger is exposed in the UI as you can see from the image
-below.
+You can take ownership of existing triggers by clicking *Take ownership*.
+From now on the trigger will be run as you.
-![Marked rebuilds as triggered on a single build page](img/trigger_single_build.png)
+## Revoking a trigger
----
+You can revoke a trigger any time by going at your project's
+**Settings ➔ Pipelines** under **Triggers** and hitting the **Revoke** button.
+The action is irreversible.
-See the [Examples](#examples) section for more details on how to actually
-trigger a rebuild.
+## Triggering a pipeline
-## Pass build variables to a trigger
+> **Notes**:
+- Valid refs are only the branches and tags. If you pass a commit SHA as a ref,
+ it will not trigger a job.
+- If your project is public, passing the token in plain text is probably not the
+ wisest idea, so you might want to use a
+ [secret variable](../variables/README.md#secret-variables) for that purpose.
-You can pass any number of arbitrary variables in the trigger API call and they
-will be available in GitLab CI so that they can be used in your `.gitlab-ci.yml`
-file. The parameter is of the form:
+To trigger a job you need to send a `POST` request to GitLab's API endpoint:
```
-variables[key]=value
+POST /projects/:id/trigger/pipeline
```
-This information is also exposed in the UI.
+The required parameters are the [trigger's `token`](#authentication-tokens)
+and the Git `ref` on which the trigger will be performed. Valid refs are the
+branch and the tag. The `:id` of a project can be found by
+[querying the API](../../api/projects.md) or by visiting the **Pipelines**
+settings page which provides self-explanatory examples.
+
+When a rerun of a pipeline is triggered, the information is exposed in GitLab's
+UI under the **Jobs** page and the jobs are marked as triggered 'by API'.
-![Build variables in UI](img/trigger_variables.png)
+![Marked rebuilds as on jobs page](img/builds_page.png)
---
-See the [Examples](#examples) section below for more details.
+You can see which trigger caused the rebuild by visiting the single job page.
+A part of the trigger's token is exposed in the UI as you can see from the image
+below.
+
+![Marked rebuilds as triggered on a single job page](img/trigger_single_build.png)
-## Examples
+---
-Using cURL you can trigger a rebuild with minimal effort, for example:
+By using cURL you can trigger a pipeline rerun with minimal effort, for example:
```bash
curl --request POST \
--form token=TOKEN \
--form ref=master \
- https://gitlab.example.com/api/v3/projects/9/trigger/builds
+ https://gitlab.example.com/api/v4/projects/9/trigger/pipeline
```
In this case, the project with ID `9` will get rebuilt on `master` branch.
@@ -93,11 +97,9 @@ Alternatively, you can pass the `token` and `ref` arguments in the query string:
```bash
curl --request POST \
- "https://gitlab.example.com/api/v3/projects/9/trigger/builds?token=TOKEN&ref=master"
+ "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline?token=TOKEN&ref=master"
```
-### Triggering a build within `.gitlab-ci.yml`
-
You can also benefit by using triggers in your `.gitlab-ci.yml`. Let's say that
you have two projects, A and B, and you want to trigger a rebuild on the `master`
branch of project B whenever a tag on project A is created. This is the job you
@@ -107,24 +109,47 @@ need to add in project's A `.gitlab-ci.yml`:
build_docs:
stage: deploy
script:
- - "curl --request POST --form token=TOKEN --form ref=master https://gitlab.example.com/api/v3/projects/9/trigger/builds"
+ - "curl --request POST --form token=TOKEN --form ref=master https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
only:
- tags
```
-Now, whenever a new tag is pushed on project A, the build will run and the
+Now, whenever a new tag is pushed on project A, the job will run and the
`build_docs` job will be executed, triggering a rebuild of project B. The
`stage: deploy` ensures that this job will run only after all jobs with
`stage: test` complete successfully.
-_**Note:** If your project is public, passing the token in plain text is
-probably not the wisest idea, so you might want to use a
-[secure variable](../variables/README.md#user-defined-variables-secure-variables)
-for that purpose._
+## Triggering a pipeline from a webhook
+
+> **Notes**:
+- Introduced in GitLab 8.14.
+- `ref` should be passed as part of the URL in order to take precedence over
+ `ref` from the webhook body that designates the branch ref that fired the
+ trigger in the source repository.
+- `ref` should be URL-encoded if it contains slashes.
+
+To trigger a job from a webhook of another project you need to add the following
+webhook URL for Push and Tag events (change the project ID, ref and token):
+
+```
+https://gitlab.example.com/api/v4/projects/9/ref/master/trigger/pipeline?token=TOKEN
+```
+
+## Making use of trigger variables
+
+You can pass any number of arbitrary variables in the trigger API call and they
+will be available in GitLab CI so that they can be used in your `.gitlab-ci.yml`
+file. The parameter is of the form:
+
+```
+variables[key]=value
+```
+
+This information is also exposed in the UI.
-### Making use of trigger variables
+![Job variables in UI](img/trigger_variables.png)
-Using trigger variables can be proven useful for a variety of reasons.
+Using trigger variables can be proven useful for a variety of reasons:
* Identifiable jobs. Since the variable is exposed in the UI you can know
why the rebuild was triggered if you pass a variable that explains the
@@ -166,17 +191,35 @@ curl --request POST \
--form token=TOKEN \
--form ref=master \
--form "variables[UPLOAD_TO_S3]=true" \
- https://gitlab.example.com/api/v3/projects/9/trigger/builds
+ https://gitlab.example.com/api/v4/projects/9/trigger/pipeline
```
-### Using cron to trigger nightly builds
+## Using cron to trigger nightly pipelines
+
+>**Note:**
+The following behavior can also be achieved through GitLab's UI with
+[pipeline schedules](../../user/project/pipelines/schedules.md).
-Whether you craft a script or just run cURL directly, you can trigger builds
-in conjunction with cron. The example below triggers a build on the `master`
+Whether you craft a script or just run cURL directly, you can trigger jobs
+in conjunction with cron. The example below triggers a job on the `master`
branch of project with ID `9` every night at `00:30`:
```bash
-30 0 * * * curl --request POST --form token=TOKEN --form ref=master https://gitlab.example.com/api/v3/projects/9/trigger/builds
+30 0 * * * curl --request POST --form token=TOKEN --form ref=master https://gitlab.example.com/api/v4/projects/9/trigger/pipeline
```
+## Legacy triggers
+
+Old triggers, created before GitLab 9.0 will be marked as legacy.
+
+Triggers with the legacy label do not have an associated user and only have
+access to the current project. They are considered deprecated and will be
+removed with one of the future versions of GitLab. You are advised to
+[take ownership](#taking-ownership) of any legacy triggers.
+
+[ee-2017]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2017
[ci-229]: https://gitlab.com/gitlab-org/gitlab-ci/merge_requests/229
+[ee]: https://about.gitlab.com/gitlab-ee/
+[variables]: ../variables/README.md
+[predef]: ../variables/README.md#predefined-variables-environment-variables
+[registry]: ../../user/project/container_registry.md
diff --git a/doc/ci/triggers/img/builds_page.png b/doc/ci/triggers/img/builds_page.png
index c2cf4b1852c..c9cc8f308f4 100644
--- a/doc/ci/triggers/img/builds_page.png
+++ b/doc/ci/triggers/img/builds_page.png
Binary files differ
diff --git a/doc/ci/triggers/img/trigger_single_build.png b/doc/ci/triggers/img/trigger_single_build.png
index fa86f0fee3d..837bbeffe9f 100644
--- a/doc/ci/triggers/img/trigger_single_build.png
+++ b/doc/ci/triggers/img/trigger_single_build.png
Binary files differ
diff --git a/doc/ci/triggers/img/trigger_variables.png b/doc/ci/triggers/img/trigger_variables.png
index b2fcc65d304..0c2a761cfa9 100644
--- a/doc/ci/triggers/img/trigger_variables.png
+++ b/doc/ci/triggers/img/trigger_variables.png
Binary files differ
diff --git a/doc/ci/triggers/img/triggers_page.png b/doc/ci/triggers/img/triggers_page.png
index 438f285ae2d..7dc8f91cf7e 100644
--- a/doc/ci/triggers/img/triggers_page.png
+++ b/doc/ci/triggers/img/triggers_page.png
Binary files differ
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 22d67bd9964..d1f9881e51b 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -1,144 +1,434 @@
-## Variables
-
-When receiving a build from GitLab CI, the runner prepares the build environment.
-It starts by setting a list of **predefined variables** (Environment Variables) and a list of **user-defined variables**
-
-The variables can be overwritten. They take precedence over each other in this order:
-1. Trigger variables
-1. Secure variables
-1. YAML-defined job-level variables
-1. YAML-defined global variables
-1. Predefined variables
-
-For example, if you define:
-1. `API_TOKEN=SECURE` as Secure Variable
-1. `API_TOKEN=YAML` as YAML-defined variable
-
-The `API_TOKEN` will take the Secure Variable value: `SECURE`.
-
-### Predefined variables (Environment Variables)
-
-| Variable | GitLab | Runner | Description |
-|-------------------------|--------|--------|-------------|
-| **CI** | all | 0.4 | Mark that build is executed in CI environment |
-| **GITLAB_CI** | all | all | Mark that build is executed in GitLab CI environment |
-| **CI_SERVER** | all | all | Mark that build is executed in CI environment |
-| **CI_SERVER_NAME** | all | all | The name of CI server that is used to coordinate builds |
-| **CI_SERVER_VERSION** | all | all | GitLab version that is used to schedule builds |
-| **CI_SERVER_REVISION** | all | all | GitLab revision that is used to schedule builds |
-| **CI_BUILD_ID** | all | all | The unique id of the current build that GitLab CI uses internally |
-| **CI_BUILD_REF** | all | all | The commit revision for which project is built |
-| **CI_BUILD_TAG** | all | 0.5 | The commit tag name. Present only when building tags. |
-| **CI_BUILD_NAME** | all | 0.5 | The name of the build as defined in `.gitlab-ci.yml` |
-| **CI_BUILD_STAGE** | all | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
-| **CI_BUILD_REF_NAME** | all | all | The branch or tag name for which project is built |
-| **CI_BUILD_REPO** | all | all | The URL to clone the Git repository |
-| **CI_BUILD_TRIGGERED** | all | 0.5 | The flag to indicate that build was [triggered] |
-| **CI_BUILD_MANUAL** | 8.12 | all | The flag to indicate that build was manually started |
-| **CI_BUILD_TOKEN** | all | 1.2 | Token used for authenticating with the GitLab Container Registry |
-| **CI_PIPELINE_ID** | 8.10 | 0.5 | The unique id of the current pipeline that GitLab CI uses internally |
-| **CI_PROJECT_ID** | all | all | The unique id of the current project that GitLab CI uses internally |
-| **CI_PROJECT_NAME** | 8.10 | 0.5 | The project name that is currently being built |
-| **CI_PROJECT_NAMESPACE**| 8.10 | 0.5 | The project namespace (username or groupname) that is currently being built |
-| **CI_PROJECT_PATH** | 8.10 | 0.5 | The namespace with project name |
-| **CI_PROJECT_URL** | 8.10 | 0.5 | The HTTP address to access project |
-| **CI_PROJECT_DIR** | all | all | The full path where the repository is cloned and where the build is run |
-| **CI_REGISTRY** | 8.10 | 0.5 | If the Container Registry is enabled it returns the address of GitLab's Container Registry |
-| **CI_REGISTRY_IMAGE** | 8.10 | 0.5 | If the Container Registry is enabled for the project it returns the address of the registry tied to the specific project |
-| **CI_RUNNER_ID** | 8.10 | 0.5 | The unique id of runner being used |
-| **CI_RUNNER_DESCRIPTION** | 8.10 | 0.5 | The description of the runner as saved in GitLab |
-| **CI_RUNNER_TAGS** | 8.10 | 0.5 | The defined runner tags |
-| **GITLAB_USER_ID** | 8.12 | all | The id of the user who started the build |
-| **GITLAB_USER_EMAIL** | 8.12 | all | The email of the user who started the build |
-
-**Some of the variables are only available when using runner with at least defined version.**
+# Variables
-Example values:
+When receiving a job from GitLab CI, the [Runner] prepares the build environment.
+It starts by setting a list of **predefined variables** (environment variables)
+and a list of **user-defined variables**.
-```bash
-export CI_BUILD_ID="50"
-export CI_BUILD_REF="1ecfd275763eff1d6b4844ea3168962458c9f27a"
-export CI_BUILD_REF_NAME="master"
-export CI_BUILD_REPO="https://gitab-ci-token:abcde-1234ABCD5678ef@gitlab.com/gitlab-org/gitlab-ce.git"
-export CI_BUILD_TAG="1.0.0"
-export CI_BUILD_NAME="spec:other"
-export CI_BUILD_STAGE="test"
-export CI_BUILD_MANUAL="true"
-export CI_BUILD_TRIGGERED="true"
-export CI_BUILD_TOKEN="abcde-1234ABCD5678ef"
-export CI_PIPELINE_ID="1000"
-export CI_PROJECT_ID="34"
-export CI_PROJECT_DIR="/builds/gitlab-org/gitlab-ce"
-export CI_PROJECT_NAME="gitlab-ce"
-export CI_PROJECT_NAMESPACE="gitlab-org"
-export CI_PROJECT_PATH="gitlab-org/gitlab-ce"
-export CI_PROJECT_URL="https://gitlab.com/gitlab-org/gitlab-ce"
-export CI_REGISTRY="registry.gitlab.com"
-export CI_REGISTRY_IMAGE="registry.gitlab.com/gitlab-org/gitlab-ce"
-export CI_RUNNER_ID="10"
-export CI_RUNNER_DESCRIPTION="my runner"
-export CI_RUNNER_TAGS="docker, linux"
-export CI_SERVER="yes"
-export CI_SERVER_NAME="GitLab"
-export CI_SERVER_REVISION="70606bf"
-export CI_SERVER_VERSION="8.9.0"
-export GITLAB_USER_ID="42"
-export GITLAB_USER_EMAIL="alexzander@sporer.com"
-```
+## Priority of variables
+
+The variables can be overwritten and they take precedence over each other in
+this order:
+
+1. [Trigger variables][triggers] (take precedence over all)
+1. [Secret variables](#secret-variables) or [protected secret variables](#protected-secret-variables)
+1. YAML-defined [job-level variables](../yaml/README.md#job-variables)
+1. YAML-defined [global variables](../yaml/README.md#variables)
+1. [Deployment variables](#deployment-variables)
+1. [Predefined variables](#predefined-variables-environment-variables) (are the
+ lowest in the chain)
+
+For example, if you define `API_TOKEN=secure` as a secret variable and
+`API_TOKEN=yaml` in your `.gitlab-ci.yml`, the `API_TOKEN` will take the value
+`secure` as the secret variables are higher in the chain.
+
+## Predefined variables (Environment variables)
+
+Some of the predefined environment variables are available only if a minimum
+version of [GitLab Runner][runner] is used. Consult the table below to find the
+version of Runner required.
+
+>**Note:**
+Starting with GitLab 9.0, we have deprecated some variables. Read the
+[9.0 Renaming](#9-0-renaming) section to find out their replacements. **You are
+strongly advised to use the new variables as we will remove the old ones in
+future GitLab releases.**
+
+| Variable | GitLab | Runner | Description |
+|-------------------------------- |--------|--------|-------------|
+| **CI** | all | 0.4 | Mark that job is executed in CI environment |
+| **CI_COMMIT_REF_NAME** | 9.0 | all | The branch or tag name for which project is built |
+| **CI_COMMIT_REF_SLUG** | 9.0 | all | `$CI_COMMIT_REF_NAME` lowercased, shortened to 63 bytes, and with everything except `0-9` and `a-z` replaced with `-`. Use in URLs and domain names. |
+| **CI_COMMIT_SHA** | 9.0 | all | The commit revision for which project is built |
+| **CI_COMMIT_TAG** | 9.0 | 0.5 | The commit tag name. Present only when building tags. |
+| **CI_DEBUG_TRACE** | all | 1.7 | Whether [debug tracing](#debug-tracing) is enabled |
+| **CI_ENVIRONMENT_NAME** | 8.15 | all | The name of the environment for this job |
+| **CI_ENVIRONMENT_SLUG** | 8.15 | all | A simplified version of the environment name, suitable for inclusion in DNS, URLs, Kubernetes labels, etc. |
+| **CI_ENVIRONMENT_URL** | 9.3 | all | The URL of the environment for this job |
+| **CI_JOB_ID** | 9.0 | all | The unique id of the current job that GitLab CI uses internally |
+| **CI_JOB_MANUAL** | 8.12 | all | The flag to indicate that job was manually started |
+| **CI_JOB_NAME** | 9.0 | 0.5 | The name of the job as defined in `.gitlab-ci.yml` |
+| **CI_JOB_STAGE** | 9.0 | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
+| **CI_JOB_TOKEN** | 9.0 | 1.2 | Token used for authenticating with the GitLab Container Registry |
+| **CI_REPOSITORY_URL** | 9.0 | all | The URL to clone the Git repository |
+| **CI_RUNNER_DESCRIPTION** | 8.10 | 0.5 | The description of the runner as saved in GitLab |
+| **CI_RUNNER_ID** | 8.10 | 0.5 | The unique id of runner being used |
+| **CI_RUNNER_TAGS** | 8.10 | 0.5 | The defined runner tags |
+| **CI_PIPELINE_ID** | 8.10 | 0.5 | The unique id of the current pipeline that GitLab CI uses internally |
+| **CI_PIPELINE_TRIGGERED** | all | all | The flag to indicate that job was [triggered] |
+| **CI_PROJECT_DIR** | all | all | The full path where the repository is cloned and where the job is run |
+| **CI_PROJECT_ID** | all | all | The unique id of the current project that GitLab CI uses internally |
+| **CI_PROJECT_NAME** | 8.10 | 0.5 | The project name that is currently being built (actually it is project folder name) |
+| **CI_PROJECT_NAMESPACE** | 8.10 | 0.5 | The project namespace (username or groupname) that is currently being built |
+| **CI_PROJECT_PATH** | 8.10 | 0.5 | The namespace with project name |
+| **CI_PROJECT_PATH_SLUG** | 9.3 | all | `$CI_PROJECT_PATH` lowercased and with everything except `0-9` and `a-z` replaced with `-`. Use in URLs and domain names. |
+| **CI_PROJECT_URL** | 8.10 | 0.5 | The HTTP address to access project |
+| **CI_REGISTRY** | 8.10 | 0.5 | If the Container Registry is enabled it returns the address of GitLab's Container Registry |
+| **CI_REGISTRY_IMAGE** | 8.10 | 0.5 | If the Container Registry is enabled for the project it returns the address of the registry tied to the specific project |
+| **CI_REGISTRY_PASSWORD** | 9.0 | all | The password to use to push containers to the GitLab Container Registry |
+| **CI_REGISTRY_USER** | 9.0 | all | The username to use to push containers to the GitLab Container Registry |
+| **CI_SERVER** | all | all | Mark that job is executed in CI environment |
+| **CI_SERVER_NAME** | all | all | The name of CI server that is used to coordinate jobs |
+| **CI_SERVER_REVISION** | all | all | GitLab revision that is used to schedule jobs |
+| **CI_SERVER_VERSION** | all | all | GitLab version that is used to schedule jobs |
+| **ARTIFACT_DOWNLOAD_ATTEMPTS** | 8.15 | 1.9 | Number of attempts to download artifacts running a job |
+| **GET_SOURCES_ATTEMPTS** | 8.15 | 1.9 | Number of attempts to fetch sources running a job |
+| **GITLAB_CI** | all | all | Mark that job is executed in GitLab CI environment |
+| **GITLAB_USER_ID** | 8.12 | all | The id of the user who started the job |
+| **GITLAB_USER_EMAIL** | 8.12 | all | The email of the user who started the job |
+| **RESTORE_CACHE_ATTEMPTS** | 8.15 | 1.9 | Number of attempts to restore the cache running a job |
+
+## 9.0 Renaming
-### YAML-defined variables
-**This feature requires GitLab Runner 0.5.0 or higher and GitLab CI 7.14 or higher **
+To follow conventions of naming across GitLab, and to futher move away from the
+`build` term and toward `job` CI variables have been renamed for the 9.0
+release.
-GitLab CI allows you to add to `.gitlab-ci.yml` variables that are set in build environment.
-The variables are stored in repository and are meant to store non-sensitive project configuration, ie. RAILS_ENV or DATABASE_URL.
+| 8.x name | 9.0+ name |
+| --------------------- |------------------------ |
+| `CI_BUILD_ID` | `CI_JOB_ID` |
+| `CI_BUILD_REF` | `CI_COMMIT_SHA` |
+| `CI_BUILD_TAG` | `CI_COMMIT_TAG` |
+| `CI_BUILD_REF_NAME` | `CI_COMMIT_REF_NAME` |
+| `CI_BUILD_REF_SLUG` | `CI_COMMIT_REF_SLUG` |
+| `CI_BUILD_NAME` | `CI_JOB_NAME` |
+| `CI_BUILD_STAGE` | `CI_JOB_STAGE` |
+| `CI_BUILD_REPO` | `CI_REPOSITORY_URL` |
+| `CI_BUILD_TRIGGERED` | `CI_PIPELINE_TRIGGERED` |
+| `CI_BUILD_MANUAL` | `CI_JOB_MANUAL` |
+| `CI_BUILD_TOKEN` | `CI_JOB_TOKEN` |
+
+## `.gitlab-ci.yaml` defined variables
+
+>**Note:**
+This feature requires GitLab Runner 0.5.0 or higher and GitLab CI 7.14 or higher.
+
+GitLab CI allows you to add to `.gitlab-ci.yml` variables that are set in the
+build environment. The variables are hence saved in the repository, and they
+are meant to store non-sensitive project configuration, e.g., `RAILS_ENV` or
+`DATABASE_URL`.
+
+For example, if you set the variable below globally (not inside a job), it will
+be used in all executed commands and scripts:
```yaml
variables:
DATABASE_URL: "postgres://postgres@postgres/my_database"
```
-These variables can be later used in all executed commands and scripts.
+The YAML-defined variables are also set to all created
+[service containers](../docker/using_docker_images.md), thus allowing to fine
+tune them.
+
+Variables can be defined at a global level, but also at a job level. To turn off
+global defined variables in your job, define an empty hash:
+
+```yaml
+job_name:
+ variables: {}
+```
+
+You are able to use other variables inside your variable definition (or escape them with `$$`):
+
+```yaml
+variables:
+ LS_CMD: 'ls $FLAGS $$TMP_DIR'
+ FLAGS: '-al'
+script:
+ - 'eval $LS_CMD' # will execute 'ls -al $TMP_DIR'
+```
+
+## Secret variables
+
+>**Notes:**
+- This feature requires GitLab Runner 0.4.0 or higher.
+- Be aware that secret variables are not masked, and their values can be shown
+ in the job logs if explicitly asked to do so. If your project is public or
+ internal, you can set the pipelines private from your project's Pipelines
+ settings. Follow the discussion in issue [#13784][ce-13784] for masking the
+ secret variables.
+
+GitLab CI allows you to define per-project **secret variables** that are set in
+the build environment. The secret variables are stored out of the repository
+(`.gitlab-ci.yml`) and are securely passed to GitLab Runner making them
+available in the build environment. It's the recommended method to use for
+storing things like passwords, secret keys and credentials.
+
+Secret variables can be added by going to your project's
+**Settings ➔ Pipelines**, then finding the section called
+**Secret variables**.
+
+Once you set them, they will be available for all subsequent pipelines.
+
+## Protected secret variables
+
+>**Notes:**
+This feature requires GitLab 9.3 or higher.
+
+Secret variables could be protected. Whenever a secret variable is
+protected, it would only be securely passed to pipelines running on the
+[protected branches] or [protected tags]. The other pipelines would not get any
+protected variables.
+
+Protected variables can be added by going to your project's
+**Settings ➔ Pipelines**, then finding the section called
+**Secret variables**, and check *Protected*.
+
+Once you set them, they will be available for all subsequent pipelines.
+
+## Deployment variables
+
+>**Note:**
+This feature requires GitLab CI 8.15 or higher.
+
+[Project services](../../user/project/integrations/project_services.md) that are
+responsible for deployment configuration may define their own variables that
+are set in the build environment. These variables are only defined for
+[deployment jobs](../environments.md). Please consult the documentation of
+the project services that you are using to learn which variables they define.
+
+An example project service that defines deployment variables is
+[Kubernetes Service](../../user/project/integrations/kubernetes.md).
+
+## Debug tracing
+
+> Introduced in GitLab Runner 1.7.
+>
+> **WARNING:** Enabling debug tracing can have severe security implications. The
+ output **will** contain the content of all your secret variables and any other
+ secrets! The output **will** be uploaded to the GitLab server and made visible
+ in job traces!
+
+By default, GitLab Runner hides most of the details of what it is doing when
+processing a job. This behaviour keeps job traces short, and prevents secrets
+from being leaked into the trace unless your script writes them to the screen.
+
+If a job isn't working as expected, this can make the problem difficult to
+investigate; in these cases, you can enable debug tracing in `.gitlab-ci.yml`.
+Available on GitLab Runner v1.7+, this feature enables the shell's execution
+trace, resulting in a verbose job trace listing all commands that were run,
+variables that were set, etc.
+
+Before enabling this, you should ensure jobs are visible to
+[team members only](../../user/permissions.md#project-features). You should
+also [erase](../pipelines.md#seeing-build-status) all generated job traces
+before making them visible again.
+
+To enable debug traces, set the `CI_DEBUG_TRACE` variable to `true`:
+
+```yaml
+job_name:
+ variables:
+ CI_DEBUG_TRACE: "true"
+```
+
+Example truncated output with debug trace set to true:
-The YAML-defined variables are also set to all created service containers, thus allowing to fine tune them.
+```bash
+...
-Variables can be defined at a global level, but also at a job level.
+export CI_SERVER_TLS_CA_FILE="/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE"
+if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
+ echo $'\''\x1b[32;1mFetching changes...\x1b[0;m'\''
+ $'\''cd'\'' "/builds/gitlab-examples/ci-debug-trace"
+ $'\''git'\'' "config" "fetch.recurseSubmodules" "false"
+ $'\''rm'\'' "-f" ".git/index.lock"
+ $'\''git'\'' "clean" "-ffdx"
+ $'\''git'\'' "reset" "--hard"
+ $'\''git'\'' "remote" "set-url" "origin" "https://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@example.com/gitlab-examples/ci-debug-trace.git"
+ $'\''git'\'' "fetch" "origin" "--prune" "+refs/heads/*:refs/remotes/origin/*" "+refs/tags/*:refs/tags/*"
+else
+ $'\''mkdir'\'' "-p" "/builds/gitlab-examples/ci-debug-trace.tmp/git-template"
+ $'\''rm'\'' "-r" "-f" "/builds/gitlab-examples/ci-debug-trace"
+ $'\''git'\'' "config" "-f" "/builds/gitlab-examples/ci-debug-trace.tmp/git-template/config" "fetch.recurseSubmodules" "false"
+ echo $'\''\x1b[32;1mCloning repository...\x1b[0;m'\''
+ $'\''git'\'' "clone" "--no-checkout" "https://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@example.com/gitlab-examples/ci-debug-trace.git" "/builds/gitlab-examples/ci-debug-trace" "--template" "/builds/gitlab-examples/ci-debug-trace.tmp/git-template"
+ $'\''cd'\'' "/builds/gitlab-examples/ci-debug-trace"
+fi
+echo $'\''\x1b[32;1mChecking out dd648b2e as master...\x1b[0;m'\''
+$'\''git'\'' "checkout" "-f" "-q" "dd648b2e48ce6518303b0bb580b2ee32fadaf045"
+'
++++ hostname
+++ echo 'Running on runner-8a2f473d-project-1796893-concurrent-0 via runner-8a2f473d-machine-1480971377-317a7d0f-digital-ocean-4gb...'
+Running on runner-8a2f473d-project-1796893-concurrent-0 via runner-8a2f473d-machine-1480971377-317a7d0f-digital-ocean-4gb...
+++ export CI=true
+++ CI=true
+++ export CI_DEBUG_TRACE=false
+++ CI_DEBUG_TRACE=false
+++ export CI_COMMIT_SHA=dd648b2e48ce6518303b0bb580b2ee32fadaf045
+++ CI_COMMIT_SHA=dd648b2e48ce6518303b0bb580b2ee32fadaf045
+++ export CI_COMMIT_BEFORE_SHA=dd648b2e48ce6518303b0bb580b2ee32fadaf045
+++ CI_COMMIT_BEFORE_SHA=dd648b2e48ce6518303b0bb580b2ee32fadaf045
+++ export CI_COMMIT_REF_NAME=master
+++ CI_COMMIT_REF_NAME=master
+++ export CI_JOB_ID=7046507
+++ CI_JOB_ID=7046507
+++ export CI_REPOSITORY_URL=https://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@example.com/gitlab-examples/ci-debug-trace.git
+++ CI_REPOSITORY_URL=https://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@example.com/gitlab-examples/ci-debug-trace.git
+++ export CI_JOB_TOKEN=xxxxxxxxxxxxxxxxxxxx
+++ CI_JOB_TOKEN=xxxxxxxxxxxxxxxxxxxx
+++ export CI_PROJECT_ID=1796893
+++ CI_PROJECT_ID=1796893
+++ export CI_PROJECT_DIR=/builds/gitlab-examples/ci-debug-trace
+++ CI_PROJECT_DIR=/builds/gitlab-examples/ci-debug-trace
+++ export CI_SERVER=yes
+++ CI_SERVER=yes
+++ export 'CI_SERVER_NAME=GitLab CI'
+++ CI_SERVER_NAME='GitLab CI'
+++ export CI_SERVER_VERSION=
+++ CI_SERVER_VERSION=
+++ export CI_SERVER_REVISION=
+++ CI_SERVER_REVISION=
+++ export GITLAB_CI=true
+++ GITLAB_CI=true
+++ export CI=true
+++ CI=true
+++ export GITLAB_CI=true
+++ GITLAB_CI=true
+++ export CI_JOB_ID=7046507
+++ CI_JOB_ID=7046507
+++ export CI_JOB_TOKEN=xxxxxxxxxxxxxxxxxxxx
+++ CI_JOB_TOKEN=xxxxxxxxxxxxxxxxxxxx
+++ export CI_COMMIT_REF=dd648b2e48ce6518303b0bb580b2ee32fadaf045
+++ CI_COMMIT_REF=dd648b2e48ce6518303b0bb580b2ee32fadaf045
+++ export CI_COMMIT_BEFORE_SHA=dd648b2e48ce6518303b0bb580b2ee32fadaf045
+++ CI_COMMIT_BEFORE_SHA=dd648b2e48ce6518303b0bb580b2ee32fadaf045
+++ export CI_COMMIT_REF_NAME=master
+++ CI_COMMIT_REF_NAME=master
+++ export CI_COMMIT_NAME=debug_trace
+++ CI_JOB_NAME=debug_trace
+++ export CI_JOB_STAGE=test
+++ CI_JOB_STAGE=test
+++ export CI_SERVER_NAME=GitLab
+++ CI_SERVER_NAME=GitLab
+++ export CI_SERVER_VERSION=8.14.3-ee
+++ CI_SERVER_VERSION=8.14.3-ee
+++ export CI_SERVER_REVISION=82823
+++ CI_SERVER_REVISION=82823
+++ export CI_PROJECT_ID=17893
+++ CI_PROJECT_ID=17893
+++ export CI_PROJECT_NAME=ci-debug-trace
+++ CI_PROJECT_NAME=ci-debug-trace
+++ export CI_PROJECT_PATH=gitlab-examples/ci-debug-trace
+++ CI_PROJECT_PATH=gitlab-examples/ci-debug-trace
+++ export CI_PROJECT_NAMESPACE=gitlab-examples
+++ CI_PROJECT_NAMESPACE=gitlab-examples
+++ export CI_PROJECT_URL=https://example.com/gitlab-examples/ci-debug-trace
+++ CI_PROJECT_URL=https://example.com/gitlab-examples/ci-debug-trace
+++ export CI_PIPELINE_ID=52666
+++ CI_PIPELINE_ID=52666
+++ export CI_RUNNER_ID=1337
+++ CI_RUNNER_ID=1337
+++ export CI_RUNNER_DESCRIPTION=shared-runners-manager-1.example.com
+++ CI_RUNNER_DESCRIPTION=shared-runners-manager-1.example.com
+++ export 'CI_RUNNER_TAGS=shared, docker, linux, ruby, mysql, postgres, mongo'
+++ CI_RUNNER_TAGS='shared, docker, linux, ruby, mysql, postgres, mongo'
+++ export CI_REGISTRY=registry.example.com
+++ CI_REGISTRY=registry.example.com
+++ export CI_DEBUG_TRACE=true
+++ CI_DEBUG_TRACE=true
+++ export GITLAB_USER_ID=42
+++ GITLAB_USER_ID=42
+++ export GITLAB_USER_EMAIL=user@example.com
+++ GITLAB_USER_EMAIL=user@example.com
+++ export VERY_SECURE_VARIABLE=imaverysecurevariable
+++ VERY_SECURE_VARIABLE=imaverysecurevariable
+++ mkdir -p /builds/gitlab-examples/ci-debug-trace.tmp
+++ echo -n '-----BEGIN CERTIFICATE-----
+MIIFQzCCBCugAwIBAgIRAL/ElDjuf15xwja1ZnCocWAwDQYJKoZIhvcNAQELBQAw'
-More information about Docker integration can be found in [Using Docker Images](../docker/using_docker_images.md).
+...
+```
-### User-defined variables (Secure Variables)
-**This feature requires GitLab Runner 0.4.0 or higher**
+## Using the CI variables in your job scripts
-GitLab CI allows you to define per-project **Secure Variables** that are set in
-the build environment.
-The secure variables are stored out of the repository (the `.gitlab-ci.yml`).
-The variables are securely passed to GitLab Runner and are available in the
-build environment.
-It's desired method to use them for storing passwords, secret keys or whatever
-you want.
+All variables are set as environment variables in the build environment, and
+they are accessible with normal methods that are used to access such variables.
+In most cases `bash` or `sh` is used to execute the job script.
-**The value of the variable can be shown in build log if explicitly asked to do so.**
-If your project is public or internal you can make the builds private.
+To access environment variables, use the syntax for your Runner's [shell][shellexecutors].
-Secure Variables can added by going to `Project > Variables > Add Variable`.
+| Shell | Usage |
+|----------------------|-----------------|
+| bash/sh | `$variable` |
+| windows batch | `%variable%` |
+| PowerShell | `$env:variable` |
-They will be available for all subsequent builds.
+To access environment variables in bash, prefix the variable name with (`$`):
-### Use variables
-The variables are set as environment variables in build environment and are accessible with normal methods that are used to access such variables.
-In most cases the **bash** is used to execute build script.
-To access variables (predefined and user-defined) in bash environment, prefix the variable name with `$`:
+```yaml
+job_name:
+ script:
+ - echo $CI_JOB_ID
```
+
+To access environment variables in **Windows Batch**, surround the variable
+with (`%`):
+
+```yaml
job_name:
script:
- - echo $CI_BUILD_ID
+ - echo %CI_JOB_ID%
```
-You can also list all environment variables with `export` command,
-but be aware that this will also expose value of all **Secure Variables** in build log:
+To access environment variables in a **Windows PowerShell** environment, prefix
+the variable name with (`$env:`):
+
+```yaml
+job_name:
+ script:
+ - echo $env:CI_JOB_ID
```
+
+You can also list all environment variables with the `export` command,
+but be aware that this will also expose the values of all the secret variables
+you set, in the job log:
+
+```yaml
job_name:
script:
- export
```
+Example values:
+
+```bash
+export CI_JOB_ID="50"
+export CI_COMMIT_SHA="1ecfd275763eff1d6b4844ea3168962458c9f27a"
+export CI_COMMIT_REF_NAME="master"
+export CI_REPOSITORY_URL="https://gitlab-ci-token:abcde-1234ABCD5678ef@example.com/gitlab-org/gitlab-ce.git"
+export CI_COMMIT_TAG="1.0.0"
+export CI_JOB_NAME="spec:other"
+export CI_JOB_STAGE="test"
+export CI_JOB_MANUAL="true"
+export CI_JOB_TRIGGERED="true"
+export CI_JOB_TOKEN="abcde-1234ABCD5678ef"
+export CI_PIPELINE_ID="1000"
+export CI_PROJECT_ID="34"
+export CI_PROJECT_DIR="/builds/gitlab-org/gitlab-ce"
+export CI_PROJECT_NAME="gitlab-ce"
+export CI_PROJECT_NAMESPACE="gitlab-org"
+export CI_PROJECT_PATH="gitlab-org/gitlab-ce"
+export CI_PROJECT_URL="https://example.com/gitlab-org/gitlab-ce"
+export CI_REGISTRY="registry.example.com"
+export CI_REGISTRY_IMAGE="registry.example.com/gitlab-org/gitlab-ce"
+export CI_RUNNER_ID="10"
+export CI_RUNNER_DESCRIPTION="my runner"
+export CI_RUNNER_TAGS="docker, linux"
+export CI_SERVER="yes"
+export CI_SERVER_NAME="GitLab"
+export CI_SERVER_REVISION="70606bf"
+export CI_SERVER_VERSION="8.9.0"
+export GITLAB_USER_ID="42"
+export GITLAB_USER_EMAIL="user@example.com"
+export CI_REGISTRY_USER="gitlab-ci-token"
+export CI_REGISTRY_PASSWORD="longalfanumstring"
+```
+
+[ce-13784]: https://gitlab.com/gitlab-org/gitlab-ce/issues/13784
+[runner]: https://docs.gitlab.com/runner/
[triggered]: ../triggers/README.md
+[triggers]: ../triggers/README.md#pass-job-variables-to-a-trigger
+[protected branches]: ../../user/project/protected_branches.md
+[protected tags]: ../../user/project/protected_tags.md
+[shellexecutors]: https://docs.gitlab.com/runner/executors/
+[eep]: https://about.gitlab.com/gitlab-ee/ "Available only in GitLab Enterprise Edition Premium"
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index cdf5ecc7a84..8a0662db6fd 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -1,7 +1,7 @@
-# Configuration of your builds with .gitlab-ci.yml
+# Configuration of your jobs with .gitlab-ci.yml
This document describes the usage of `.gitlab-ci.yml`, the file that is used by
-GitLab Runner to manage your project's builds.
+GitLab Runner to manage your project's jobs.
If you want a quick introduction to GitLab CI, follow our
[quick start guide](../quick_start/README.md).
@@ -30,10 +30,9 @@ jobs, where each of the jobs executes a different command.
Of course a command can execute code directly (`./configure;make;make install`)
or run a script (`test.sh`) in the repository.
-Jobs are used to create builds, which are then picked up by
-[Runners](../runners/README.md) and executed within the environment of the
-Runner. What is important, is that each job is run independently from each
-other.
+Jobs are picked up by [Runners](../runners/README.md) and executed within the
+environment of the Runner. What is important, is that each job is run
+independently from each other.
The YAML syntax allows for using more complex job specifications than in the
above example:
@@ -71,7 +70,7 @@ There are a few reserved `keywords` that **cannot** be used as job names:
| image | no | Use docker image, covered in [Use Docker](../docker/README.md) |
| services | no | Use docker services, covered in [Use Docker](../docker/README.md) |
| stages | no | Define build stages |
-| types | no | Alias for `stages` |
+| types | no | Alias for `stages` (deprecated) |
| before_script | no | Define commands that run before each job's script |
| after_script | no | Define commands that run after each job's script |
| variables | no | Define build variables |
@@ -80,30 +79,31 @@ There are a few reserved `keywords` that **cannot** be used as job names:
### image and services
This allows to specify a custom Docker image and a list of services that can be
-used for time of the build. The configuration of this feature is covered in
+used for time of the job. The configuration of this feature is covered in
[a separate document](../docker/README.md).
### before_script
`before_script` is used to define the command that should be run before all
-builds, including deploy builds. This can be an array or a multi-line string.
+jobs, including deploy jobs, but after the restoration of artifacts. This can
+be an array or a multi-line string.
### after_script
> Introduced in GitLab 8.7 and requires Gitlab Runner v1.2
`after_script` is used to define the command that will be run after for all
-builds. This has to be an array or a multi-line string.
+jobs. This has to be an array or a multi-line string.
### stages
-`stages` is used to define build stages that can be used by jobs.
+`stages` is used to define stages that can be used by jobs.
The specification of `stages` allows for having flexible multi stage pipelines.
-The ordering of elements in `stages` defines the ordering of builds' execution:
+The ordering of elements in `stages` defines the ordering of jobs' execution:
-1. Builds of the same stage are run in parallel.
-1. Builds of the next stage are run after the jobs from the previous stage
+1. Jobs of the same stage are run in parallel.
+1. Jobs of the next stage are run after the jobs from the previous stage
complete successfully.
Let's consider the following example, which defines 3 stages:
@@ -115,7 +115,7 @@ stages:
- deploy
```
-1. First all jobs of `build` are executed in parallel.
+1. First, all jobs of `build` are executed in parallel.
1. If all jobs of `build` succeed, the `test` jobs are executed in parallel.
1. If all jobs of `test` succeed, the `deploy` jobs are executed in parallel.
1. If all jobs of `deploy` succeed, the commit is marked as `success`.
@@ -124,12 +124,14 @@ stages:
There are also two edge cases worth mentioning:
-1. If no `stages` are defined in `.gitlab-ci.yml`, then by default the `build`,
+1. If no `stages` are defined in `.gitlab-ci.yml`, then the `build`,
`test` and `deploy` are allowed to be used as job's stage by default.
2. If a job doesn't specify a `stage`, the job is assigned the `test` stage.
### types
+> Deprecated, and will be removed in 10.0. Use [stages](#stages) instead.
+
Alias for [stages](#stages).
### variables
@@ -137,7 +139,7 @@ Alias for [stages](#stages).
> Introduced in GitLab Runner v0.5.0.
GitLab CI allows you to add variables to `.gitlab-ci.yml` that are set in the
-build environment. The variables are stored in the Git repository and are meant
+job environment. The variables are stored in the Git repository and are meant
to store non-sensitive project configuration, for example:
```yaml
@@ -145,26 +147,40 @@ variables:
DATABASE_URL: "postgres://postgres@postgres/my_database"
```
-These variables can be later used in all executed commands and scripts.
+>**Note:**
+Integers (as well as strings) are legal both for variable's name and value.
+Floats are not legal and cannot be used.
+These variables can be later used in all executed commands and scripts.
The YAML-defined variables are also set to all created service containers,
-thus allowing to fine tune them.
+thus allowing to fine tune them. Variables can be also defined on a
+[job level](#job-variables).
-Variables can be also defined on [job level](#job-variables).
+Except for the user defined variables, there are also the ones set up by the
+Runner itself. One example would be `CI_COMMIT_REF_NAME` which has the value of
+the branch or tag name for which project is built. Apart from the variables
+you can set in `.gitlab-ci.yml`, there are also the so called secret variables
+which can be set in GitLab's UI.
-[Learn more about variables.](../variables/README.md)
+[Learn more about variables.][variables]
### cache
-> Introduced in GitLab Runner v0.7.0.
+>
+**Notes:**
+- Introduced in GitLab Runner v0.7.0.
+- Prior to GitLab 9.2, caches were restored after artifacts.
+- From GitLab 9.2, caches are restored before artifacts.
`cache` is used to specify a list of files and directories which should be
-cached between builds.
+cached between jobs. You can only use paths that are within the project
+workspace.
-**By default the caching is enabled per-job and per-branch.**
+**By default caching is enabled and shared between pipelines and jobs,
+starting from GitLab 9.0**
-If `cache` is defined outside the scope of the jobs, it means it is set
-globally and all jobs will use its definition.
+If `cache` is defined outside the scope of jobs, it means it is set
+globally and all jobs will use that definition.
Cache all files in `binaries` and `.config`:
@@ -197,8 +213,8 @@ rspec:
- binaries/
```
-Locally defined cache overwrites globally defined options. This will cache only
-`binaries/`:
+Locally defined cache overrides globally defined options. The following `rspec`
+job will cache only `binaries/`:
```yaml
cache:
@@ -208,10 +224,15 @@ cache:
rspec:
script: test
cache:
+ key: rspec
paths:
- binaries/
```
+Note that since cache is shared between jobs, if you're using different
+paths for different jobs, you should also set a different **cache:key**
+otherwise cache content can be overwritten.
+
The cache is provided on a best-effort basis, so don't expect that the cache
will be always present. For implementation details, please check GitLab Runner.
@@ -228,6 +249,9 @@ different jobs or even different branches.
The `cache:key` variable can use any of the [predefined variables](../variables/README.md).
+The default key is **default** across the project, therefore everything is
+shared between each pipelines and jobs by default, starting from GitLab 9.0.
+
---
**Example configurations**
@@ -236,7 +260,7 @@ To enable per-job caching:
```yaml
cache:
- key: "$CI_BUILD_NAME"
+ key: "$CI_JOB_NAME"
untracked: true
```
@@ -244,7 +268,7 @@ To enable per-branch caching:
```yaml
cache:
- key: "$CI_BUILD_REF_NAME"
+ key: "$CI_COMMIT_REF_NAME"
untracked: true
```
@@ -252,7 +276,7 @@ To enable per-job and per-branch caching:
```yaml
cache:
- key: "$CI_BUILD_NAME/$CI_BUILD_REF_NAME"
+ key: "$CI_JOB_NAME/$CI_COMMIT_REF_NAME"
untracked: true
```
@@ -260,7 +284,7 @@ To enable per-branch and per-stage caching:
```yaml
cache:
- key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME"
+ key: "$CI_JOB_STAGE/$CI_COMMIT_REF_NAME"
untracked: true
```
@@ -269,15 +293,24 @@ If you use **Windows Batch** to run your shell scripts you need to replace
```yaml
cache:
- key: "%CI_BUILD_STAGE%/%CI_BUILD_REF_NAME%"
+ key: "%CI_JOB_STAGE%/%CI_COMMIT_REF_NAME%"
+ untracked: true
+```
+
+If you use **Windows PowerShell** to run your shell scripts you need to replace
+`$` with `$env:`:
+
+```yaml
+cache:
+ key: "$env:CI_JOB_STAGE/$env:CI_COMMIT_REF_NAME"
untracked: true
```
## Jobs
`.gitlab-ci.yml` allows you to specify an unlimited number of jobs. Each job
-must have a unique name, which is not one of the Keywords mentioned above.
-A job is defined by a list of parameters that define the build behavior.
+must have a unique name, which is not one of the keywords mentioned above.
+A job is defined by a list of parameters that define the job behavior.
```yaml
job_name:
@@ -297,23 +330,24 @@ job_name:
| Keyword | Required | Description |
|---------------|----------|-------------|
-| script | yes | Defines a shell script which is executed by Runner |
-| image | no | Use docker image, covered in [Using Docker Images](../docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml) |
-| services | no | Use docker services, covered in [Using Docker Images](../docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml) |
-| stage | no | Defines a build stage (default: `test`) |
-| type | no | Alias for `stage` |
-| variables | no | Define build variables on a job level |
-| only | no | Defines a list of git refs for which build is created |
-| except | no | Defines a list of git refs for which build is not created |
-| tags | no | Defines a list of tags which are used to select Runner |
-| allow_failure | no | Allow build to fail. Failed build doesn't contribute to commit status |
-| when | no | Define when to run build. Can be `on_success`, `on_failure`, `always` or `manual` |
-| dependencies | no | Define other builds that a build depends on so that you can pass artifacts between them|
-| artifacts | no | Define list of build artifacts |
-| cache | no | Define list of files that should be cached between subsequent runs |
-| before_script | no | Override a set of commands that are executed before build |
-| after_script | no | Override a set of commands that are executed after build |
-| environment | no | Defines a name of environment to which deployment is done by this build |
+| script | yes | Defines a shell script which is executed by Runner |
+| image | no | Use docker image, covered in [Using Docker Images](../docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml) |
+| services | no | Use docker services, covered in [Using Docker Images](../docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml) |
+| stage | no | Defines a job stage (default: `test`) |
+| type | no | Alias for `stage` |
+| variables | no | Define job variables on a job level |
+| only | no | Defines a list of git refs for which job is created |
+| except | no | Defines a list of git refs for which job is not created |
+| tags | no | Defines a list of tags which are used to select Runner |
+| allow_failure | no | Allow job to fail. Failed job doesn't contribute to commit status |
+| when | no | Define when to run job. Can be `on_success`, `on_failure`, `always` or `manual` |
+| dependencies | no | Define other jobs that a job depends on so that you can pass artifacts between them|
+| artifacts | no | Define list of [job artifacts](../../user/project/pipelines/job_artifacts.md) |
+| cache | no | Define list of files that should be cached between subsequent runs |
+| before_script | no | Override a set of commands that are executed before job |
+| after_script | no | Override a set of commands that are executed after job |
+| environment | no | Defines a name of environment to which deployment is done by this job |
+| coverage | no | Define code coverage settings for a given job |
### script
@@ -333,11 +367,15 @@ job:
- bundle exec rspec
```
-Sometimes, `script` commands will need to be wrapped in single or double quotes. For example, commands that contain a colon (`:`) need to be wrapped in quotes so that the YAML parser knows to interpret the whole thing as a string rather than a "key: value" pair. Be careful when using special characters (`:`, `{`, `}`, `[`, `]`, `,`, `&`, `*`, `#`, `?`, `|`, `-`, `<`, `>`, `=`, `!`, `%`, `@`, `` ` ``).
+Sometimes, `script` commands will need to be wrapped in single or double quotes.
+For example, commands that contain a colon (`:`) need to be wrapped in quotes so
+that the YAML parser knows to interpret the whole thing as a string rather than
+a "key: value" pair. Be careful when using special characters:
+`:`, `{`, `}`, `[`, `]`, `,`, `&`, `*`, `#`, `?`, `|`, `-`, `<`, `>`, `=`, `!`, `%`, `@`, `` ` ``.
### stage
-`stage` allows to group build into different stages. Builds of the same `stage`
+`stage` allows to group jobs into different stages. Jobs of the same `stage`
are executed in `parallel`. For more info about the use of `stage` please check
[stages](#stages).
@@ -346,17 +384,17 @@ are executed in `parallel`. For more info about the use of `stage` please check
`only` and `except` are two parameters that set a refs policy to limit when
jobs are built:
-1. `only` defines the names of branches and tags for which the job will be
- built.
+1. `only` defines the names of branches and tags for which the job will run.
2. `except` defines the names of branches and tags for which the job will
- **not** be built.
+ **not** run.
There are a few rules that apply to the usage of refs policy:
* `only` and `except` are inclusive. If both `only` and `except` are defined
in a job specification, the ref is filtered by `only` and `except`.
* `only` and `except` allow the use of regular expressions.
-* `only` and `except` allow the use of special keywords: `branches`, `tags`, and `triggers`.
+* `only` and `except` allow the use of special keywords:
+`api`, `branches`, `external`, `tags`, `pushes`, `schedules`, `triggers`, and `web`
* `only` and `except` allow to specify a repository path to filter jobs for
forks.
@@ -373,8 +411,8 @@ job:
- branches
```
-In this example, `job` will run only for refs that are tagged, or if a build is explicitly requested
-via an API trigger.
+In this example, `job` will run only for refs that are tagged, or if a build is
+explicitly requested via an API trigger or a [Pipeline Schedule](../../user/project/pipelines/schedules.md).
```yaml
job:
@@ -382,6 +420,7 @@ job:
only:
- tags
- triggers
+ - schedules
```
The repository path can be used to have jobs executed only for the parent
@@ -398,17 +437,22 @@ job:
The above example will run `job` for all branches on `gitlab-org/gitlab-ce`,
except master.
-### job variables
+### Job variables
-It is possible to define build variables using a `variables` keyword on a job
-level. It works basically the same way as its global-level equivalent but
-allows you to define job-specific build variables.
+It is possible to define job variables using a `variables` keyword on a job
+level. It works basically the same way as its [global-level equivalent](#variables),
+but allows you to define job-specific variables.
-When the `variables` keyword is used on a job level, it overrides global YAML
-build variables and predefined variables.
+When the `variables` keyword is used on a job level, it overrides the global YAML
+job variables and predefined ones. To turn off global defined variables
+in your job, define an empty hash:
+
+```yaml
+job_name:
+ variables: {}
+```
-Build variables priority is defined in
-[variables documentation](../variables/README.md).
+Job variables priority is defined in the [variables documentation][variables].
### tags
@@ -418,7 +462,7 @@ allowed to run this project.
During the registration of a Runner, you can specify the Runner's tags, for
example `ruby`, `postgres`, `development`.
-`tags` allow you to run builds with Runners that have the specified tags
+`tags` allow you to run jobs with Runners that have the specified tags
assigned to them:
```yaml
@@ -433,13 +477,13 @@ has both `ruby` AND `postgres` tags defined.
### allow_failure
-`allow_failure` is used when you want to allow a build to fail without impacting
-the rest of the CI suite. Failed builds don't contribute to the commit status.
+`allow_failure` is used when you want to allow a job to fail without impacting
+the rest of the CI suite. Failed jobs don't contribute to the commit status.
-When enabled and the build fails, the pipeline will be successful/green for all
+When enabled and the job fails, the pipeline will be successful/green for all
intents and purposes, but a "CI build passed with warnings" message will be
-displayed on the merge request or commit or build page. This is to be used by
-builds that are allowed to fail, but where failure indicates some other (manual)
+displayed on the merge request or commit or job page. This is to be used by
+jobs that are allowed to fail, but where failure indicates some other (manual)
steps should be taken elsewhere.
In the example below, `job1` and `job2` will run in parallel, but if `job1`
@@ -471,12 +515,12 @@ failure.
`when` can be set to one of the following values:
-1. `on_success` - execute build only when all builds from prior stages
+1. `on_success` - execute job only when all jobs from prior stages
succeed. This is the default.
-1. `on_failure` - execute build only when at least one build from prior stages
+1. `on_failure` - execute job only when at least one job from prior stages
fails.
-1. `always` - execute build regardless of the status of builds from prior stages.
-1. `manual` - execute build manually (added in GitLab 8.10). Read about
+1. `always` - execute job regardless of the status of jobs from prior stages.
+1. `manual` - execute job manually (added in GitLab 8.10). Read about
[manual actions](#manual-actions) below.
For example:
@@ -514,7 +558,7 @@ deploy_job:
cleanup_job:
stage: cleanup
script:
- - cleanup after builds
+ - cleanup after jobs
when: always
```
@@ -528,85 +572,230 @@ The above script will:
#### Manual actions
> Introduced in GitLab 8.10.
+> Blocking manual actions were introduced in GitLab 9.0
+> Protected actions were introduced in GitLab 9.2
Manual actions are a special type of job that are not executed automatically;
they need to be explicitly started by a user. Manual actions can be started
-from pipeline, build, environment, and deployment views. You can execute the
-same manual action multiple times.
+from pipeline, build, environment, and deployment views.
An example usage of manual actions is deployment to production.
-### environment
+Read more at the [environments documentation][env-manual].
+
+Manual actions can be either optional or blocking. Blocking manual action will
+block execution of the pipeline at stage this action is defined in. It is
+possible to resume execution of the pipeline when someone executes a blocking
+manual actions by clicking a _play_ button.
+
+When pipeline is blocked it will not be merged if Merge When Pipeline Succeeds
+is set. Blocked pipelines also do have a special status, called _manual_.
-> Introduced in GitLab 8.9.
+Manual actions are non-blocking by default. If you want to make manual action
+blocking, it is necessary to add `allow_failure: false` to the job's definition
+in `.gitlab-ci.yml`.
-`environment` is used to define that a job deploys to a specific [environment].
-This allows easy tracking of all deployments to your environments straight from
-GitLab.
+Optional manual actions have `allow_failure: true` set by default.
+**Statuses of optional actions do not contribute to overall pipeline status.**
+
+**Manual actions are considered to be write actions, so permissions for
+protected branches are used when user wants to trigger an action. In other
+words, in order to trigger a manual action assigned to a branch that the
+pipeline is running for, user needs to have ability to merge to this branch.**
+
+### environment
+
+>
+**Notes:**
+- Introduced in GitLab 8.9.
+- You can read more about environments and find more examples in the
+ [documentation about environments][environment].
+
+`environment` is used to define that a job deploys to a specific environment.
If `environment` is specified and no environment under that name exists, a new
one will be created automatically.
-The `environment` name must contain only letters, digits, '-', '_', '/', '$', '{', '}' and spaces. Common
-names are `qa`, `staging`, and `production`, but you can use whatever name works
-with your workflow.
+In its simplest form, the `environment` keyword can be defined like:
----
+```yaml
+deploy to production:
+ stage: deploy
+ script: git push production HEAD:master
+ environment:
+ name: production
+```
-**Example configurations**
+In the above example, the `deploy to production` job will be marked as doing a
+deployment to the `production` environment.
+
+#### environment:name
+>
+**Notes:**
+- Introduced in GitLab 8.11.
+- Before GitLab 8.11, the name of an environment could be defined as a string like
+ `environment: production`. The recommended way now is to define it under the
+ `name` keyword.
+
+The `environment` name can contain:
+
+- letters
+- digits
+- spaces
+- `-`
+- `_`
+- `/`
+- `$`
+- `{`
+- `}`
+
+Common names are `qa`, `staging`, and `production`, but you can use whatever
+name works with your workflow.
+
+Instead of defining the name of the environment right after the `environment`
+keyword, it is also possible to define it as a separate value. For that, use
+the `name` keyword under `environment`:
+
+```yaml
+deploy to production:
+ stage: deploy
+ script: git push production HEAD:master
+ environment:
+ name: production
```
+
+#### environment:url
+
+>
+**Notes:**
+- Introduced in GitLab 8.11.
+- Before GitLab 8.11, the URL could be added only in GitLab's UI. The
+ recommended way now is to define it in `.gitlab-ci.yml`.
+
+This is an optional value that when set, it exposes buttons in various places
+in GitLab which when clicked take you to the defined URL.
+
+In the example below, if the job finishes successfully, it will create buttons
+in the merge requests and in the environments/deployments pages which will point
+to `https://prod.example.com`.
+
+```yaml
deploy to production:
stage: deploy
script: git push production HEAD:master
- environment: production
+ environment:
+ name: production
+ url: https://prod.example.com
```
-The `deploy to production` job will be marked as doing deployment to
-`production` environment.
+#### environment:on_stop
-#### dynamic environments
+>
+**Notes:**
+- [Introduced][ce-6669] in GitLab 8.13.
+- Starting with GitLab 8.14, when you have an environment that has a stop action
+ defined, GitLab will automatically trigger a stop action when the associated
+ branch is deleted.
-> [Introduced][ce-6323] in GitLab 8.12 and GitLab Runner 1.6.
+Closing (stoping) environments can be achieved with the `on_stop` keyword defined under
+`environment`. It declares a different job that runs in order to close
+the environment.
-`environment` can also represent a configuration hash with `name` and `url`.
-These parameters can use any of the defined CI [variables](#variables)
-(including predefined, secure variables and `.gitlab-ci.yml` variables).
+Read the `environment:action` section for an example.
-The common use case is to create dynamic environments for branches and use them
-as review apps.
+#### environment:action
----
+> [Introduced][ce-6669] in GitLab 8.13.
-**Example configurations**
+The `action` keyword is to be used in conjunction with `on_stop` and is defined
+in the job that is called to close the environment.
+
+Take for instance:
+```yaml
+review_app:
+ stage: deploy
+ script: make deploy-app
+ environment:
+ name: review
+ on_stop: stop_review_app
+
+stop_review_app:
+ stage: deploy
+ script: make delete-app
+ when: manual
+ environment:
+ name: review
+ action: stop
```
+
+In the above example we set up the `review_app` job to deploy to the `review`
+environment, and we also defined a new `stop_review_app` job under `on_stop`.
+Once the `review_app` job is successfully finished, it will trigger the
+`stop_review_app` job based on what is defined under `when`. In this case we
+set it up to `manual` so it will need a [manual action](#manual-actions) via
+GitLab's web interface in order to run.
+
+The `stop_review_app` job is **required** to have the following keywords defined:
+
+- `when` - [reference](#when)
+- `environment:name`
+- `environment:action`
+- `stage` should be the same as the `review_app` in order for the environment
+ to stop automatically when the branch is deleted
+
+#### dynamic environments
+
+>
+**Notes:**
+- [Introduced][ce-6323] in GitLab 8.12 and GitLab Runner 1.6.
+- The `$CI_ENVIRONMENT_SLUG` was [introduced][ce-7983] in GitLab 8.15.
+
+`environment` can also represent a configuration hash with `name` and `url`.
+These parameters can use any of the defined [CI variables](#variables)
+(including predefined, secure variables and `.gitlab-ci.yml` variables).
+
+For example:
+
+```yaml
deploy as review app:
stage: deploy
- script: ...
+ script: make deploy
environment:
- name: review-apps/$CI_BUILD_REF_NAME
- url: https://$CI_BUILD_REF_NAME.review.example.com/
+ name: review/$CI_COMMIT_REF_NAME
+ url: https://$CI_ENVIRONMENT_SLUG.example.com/
```
The `deploy as review app` job will be marked as deployment to dynamically
-create the `review-apps/branch-name` environment.
+create the `review/$CI_COMMIT_REF_NAME` environment, where `$CI_COMMIT_REF_NAME`
+is an [environment variable][variables] set by the Runner. The
+`$CI_ENVIRONMENT_SLUG` variable is based on the environment name, but suitable
+for inclusion in URLs. In this case, if the `deploy as review app` job was run
+in a branch named `pow`, this environment would be accessible with an URL like
+`https://review-pow.example.com/`.
-This environment should be accessible under `https://branch-name.review.example.com/`.
+This of course implies that the underlying server which hosts the application
+is properly configured.
+
+The common use case is to create dynamic environments for branches and use them
+as Review Apps. You can see a simple example using Review Apps at
+<https://gitlab.com/gitlab-examples/review-apps-nginx/>.
### artifacts
->**Notes:**
>
-> - Introduced in GitLab Runner v0.7.0 for non-Windows platforms.
-> - Windows support was added in GitLab Runner v.1.0.0.
-> - Currently not all executors are supported.
-> - Build artifacts are only collected for successful builds by default.
+**Notes:**
+- Introduced in GitLab Runner v0.7.0 for non-Windows platforms.
+- Windows support was added in GitLab Runner v.1.0.0.
+- Prior to GitLab 9.2, caches were restored after artifacts.
+- From GitLab 9.2, caches are restored before artifacts.
+- Currently not all executors are supported.
+- Job artifacts are only collected for successful jobs by default.
`artifacts` is used to specify a list of files and directories which should be
-attached to the build after success. To pass artifacts between different builds,
-see [dependencies](#dependencies).
-
+attached to the job after success. You can only use paths that are within the
+project workspace. To pass artifacts between different jobs, see [dependencies](#dependencies).
Below are some examples.
Send all files in `binaries` and `.config`:
@@ -634,6 +823,15 @@ artifacts:
- binaries/
```
+To disable artifact passing, define the job with empty [dependencies](#dependencies):
+
+```yaml
+job:
+ stage: build
+ script: make build
+ dependencies: []
+```
+
You may want to create artifacts only for tagged releases to avoid filling the
build server storage with temporary build artifacts.
@@ -656,7 +854,7 @@ release-job:
- tags
```
-The artifacts will be sent to GitLab after a successful build and will
+The artifacts will be sent to GitLab after the job finishes successfully and will
be available for download in the GitLab UI.
#### artifacts:name
@@ -673,12 +871,12 @@ The default name is `artifacts`, which becomes `artifacts.zip` when downloaded.
**Example configurations**
-To create an archive with a name of the current build:
+To create an archive with a name of the current job:
```yaml
job:
artifacts:
- name: "$CI_BUILD_NAME"
+ name: "$CI_JOB_NAME"
```
To create an archive with a name of the current branch or tag including only
@@ -687,17 +885,17 @@ the files that are untracked by Git:
```yaml
job:
artifacts:
- name: "$CI_BUILD_REF_NAME"
+ name: "$CI_COMMIT_REF_NAME"
untracked: true
```
-To create an archive with a name of the current build and the current branch or
+To create an archive with a name of the current job and the current branch or
tag including only the files that are untracked by Git:
```yaml
job:
artifacts:
- name: "${CI_BUILD_NAME}_${CI_BUILD_REF_NAME}"
+ name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
untracked: true
```
@@ -706,7 +904,7 @@ To create an archive with a name of the current [stage](#stages) and branch name
```yaml
job:
artifacts:
- name: "${CI_BUILD_STAGE}_${CI_BUILD_REF_NAME}"
+ name: "${CI_JOB_STAGE}_${CI_COMMIT_REF_NAME}"
untracked: true
```
@@ -718,7 +916,17 @@ If you use **Windows Batch** to run your shell scripts you need to replace
```yaml
job:
artifacts:
- name: "%CI_BUILD_STAGE%_%CI_BUILD_REF_NAME%"
+ name: "%CI_JOB_STAGE%_%CI_COMMIT_REF_NAME%"
+ untracked: true
+```
+
+If you use **Windows PowerShell** to run your shell scripts you need to replace
+`$` with `$env:`:
+
+```yaml
+job:
+ artifacts:
+ name: "$env:CI_JOB_STAGE_$env:CI_COMMIT_REF_NAME"
untracked: true
```
@@ -726,20 +934,20 @@ job:
> Introduced in GitLab 8.9 and GitLab Runner v1.3.0.
-`artifacts:when` is used to upload artifacts on build failure or despite the
+`artifacts:when` is used to upload artifacts on job failure or despite the
failure.
`artifacts:when` can be set to one of the following values:
-1. `on_success` - upload artifacts only when the build succeeds. This is the default.
-1. `on_failure` - upload artifacts only when the build fails.
-1. `always` - upload artifacts regardless of the build status.
+1. `on_success` - upload artifacts only when the job succeeds. This is the default.
+1. `on_failure` - upload artifacts only when the job fails.
+1. `always` - upload artifacts regardless of the job status.
---
**Example configurations**
-To upload artifacts only when build fails.
+To upload artifacts only when job fails.
```yaml
job:
@@ -756,13 +964,14 @@ time. By default, artifacts are stored on GitLab forever. `expire_in` allows you
to specify how long artifacts should live before they expire, counting from the
time they are uploaded and stored on GitLab.
-You can use the **Keep** button on the build page to override expiration and
+You can use the **Keep** button on the job page to override expiration and
keep artifacts forever.
After expiry, artifacts are actually deleted hourly by default (via a cron job),
but they are not accessible after expiry.
The value of `expire_in` is an elapsed time. Examples of parseable values:
+
- '3 mins 4 sec'
- '2 hrs 20 min'
- '2h20min'
@@ -787,14 +996,14 @@ job:
> Introduced in GitLab 8.6 and GitLab Runner v1.1.1.
This feature should be used in conjunction with [`artifacts`](#artifacts) and
-allows you to define the artifacts to pass between different builds.
+allows you to define the artifacts to pass between different jobs.
Note that `artifacts` from all previous [stages](#stages) are passed by default.
To use this feature, define `dependencies` in context of the job and pass
-a list of all previous builds from which the artifacts should be downloaded.
-You can only define builds from stages that are executed before the current one.
-An error will be shown if you define builds from the current stage or next ones.
+a list of all previous jobs from which the artifacts should be downloaded.
+You can only define jobs from stages that are executed before the current one.
+An error will be shown if you define jobs from the current stage or next ones.
Defining an empty array will skip downloading any artifacts for that job.
---
@@ -804,7 +1013,7 @@ In the following example, we define two jobs with artifacts, `build:osx` and
will be downloaded and extracted in the context of the build. The same happens
for `test:linux` and artifacts from `build:linux`.
-The job `deploy` will download artifacts from all previous builds because of
+The job `deploy` will download artifacts from all previous jobs because of
the [stage](#stages) precedence:
```yaml
@@ -841,7 +1050,7 @@ deploy:
### before_script and after_script
-It's possible to overwrite globally defined `before_script` and `after_script`:
+It's possible to overwrite the globally defined `before_script` and `after_script`:
```yaml
before_script:
@@ -856,6 +1065,26 @@ job:
- execute this after my script
```
+### coverage
+
+**Notes:**
+- [Introduced][ce-7447] in GitLab 8.17.
+
+`coverage` allows you to configure how code coverage will be extracted from the
+job output.
+
+Regular expressions are the only valid kind of value expected here. So, using
+surrounding `/` is mandatory in order to consistently and explicitly represent
+a regular expression string. You must escape special characters if you want to
+match them literally.
+
+A simple example:
+
+```yaml
+job1:
+ coverage: '/Code coverage: \d+\.\d+/'
+```
+
## Git Strategy
> Introduced in GitLab 8.9 as an experimental feature. May change or be removed
@@ -872,7 +1101,7 @@ There are three possible values: `clone`, `fetch`, and `none`.
`clone` is the slowest option. It clones the repository from scratch for every
job, ensuring that the project workspace is always pristine.
-```
+```yaml
variables:
GIT_STRATEGY: clone
```
@@ -881,7 +1110,7 @@ variables:
if it doesn't exist). `git clean` is used to undo any changes made by the last
job, and `git fetch` is used to retrieve commits made since the last job ran.
-```
+```yaml
variables:
GIT_STRATEGY: fetch
```
@@ -892,11 +1121,104 @@ for jobs that operate exclusively on artifacts (e.g., `deploy`). Git repository
data may be present, but it is certain to be out of date, so you should only
rely on files brought into the project workspace from cache or artifacts.
-```
+```yaml
variables:
GIT_STRATEGY: none
```
+## Git Checkout
+
+> Introduced in GitLab Runner 9.3
+
+The `GIT_CHECKOUT` variable can be used when the `GIT_STRATEGY` is set to either
+`clone` or `fetch` to specify whether a `git checkout` should be run. If not
+specified, it defaults to true. Like `GIT_STRATEGY`, it can be set in either the
+global [`variables`](#variables) section or the [`variables`](#job-variables)
+section for individual jobs.
+
+If set to `false`, the Runner will:
+
+- when doing `fetch` - update the repository and leave working copy on
+ the current revision,
+- when doing `clone` - clone the repository and leave working copy on the
+ default branch.
+
+Having this setting set to `true` will mean that for both `clone` and `fetch`
+strategies the Runner will checkout the working copy to a revision related
+to the CI pipeline:
+
+```yaml
+variables:
+ GIT_STRATEGY: clone
+ GIT_CHECKOUT: false
+script:
+ - git checkout master
+ - git merge $CI_BUILD_REF_NAME
+```
+
+## Git Submodule Strategy
+
+> Requires GitLab Runner v1.10+.
+
+The `GIT_SUBMODULE_STRATEGY` variable is used to control if / how Git
+submodules are included when fetching the code before a build. Like
+`GIT_STRATEGY`, it can be set in either the global [`variables`](#variables)
+section or the [`variables`](#job-variables) section for individual jobs.
+
+There are three possible values: `none`, `normal`, and `recursive`:
+
+- `none` means that submodules will not be included when fetching the project
+ code. This is the default, which matches the pre-v1.10 behavior.
+
+- `normal` means that only the top-level submodules will be included. It is
+ equivalent to:
+
+ ```
+ git submodule sync
+ git submodule update --init
+ ```
+
+- `recursive` means that all submodules (including submodules of submodules)
+ will be included. It is equivalent to:
+
+ ```
+ git submodule sync --recursive
+ git submodule update --init --recursive
+ ```
+
+Note that for this feature to work correctly, the submodules must be configured
+(in `.gitmodules`) with either:
+
+- the HTTP(S) URL of a publicly-accessible repository, or
+- a relative path to another repository on the same GitLab server. See the
+ [Git submodules](../git_submodules.md) documentation.
+
+
+## Job stages attempts
+
+> Introduced in GitLab, it requires GitLab Runner v1.9+.
+
+You can set the number for attempts the running job will try to execute each
+of the following stages:
+
+| Variable | Description |
+|-------------------------------- |-------------|
+| **GET_SOURCES_ATTEMPTS** | Number of attempts to fetch sources running a job |
+| **ARTIFACT_DOWNLOAD_ATTEMPTS** | Number of attempts to download artifacts running a job |
+| **RESTORE_CACHE_ATTEMPTS** | Number of attempts to restore the cache running a job |
+
+The default is one single attempt.
+
+Example:
+
+```yaml
+variables:
+ GET_SOURCES_ATTEMPTS: 3
+```
+
+You can set them in the global [`variables`](#variables) section or the
+[`variables`](#job-variables) section for individual jobs.
+
## Shallow cloning
> Introduced in GitLab 8.9 as an experimental feature. May change in future
@@ -908,21 +1230,22 @@ repositories with a large number of commits or old, large binaries. The value is
passed to `git fetch` and `git clone`.
>**Note:**
-If you use a depth of 1 and have a queue of builds or retry
-builds, jobs may fail.
+If you use a depth of 1 and have a queue of jobs or retry
+jobs, jobs may fail.
-Since Git fetching and cloning is based on a ref, such as a branch name, runners
-can't clone a specific commit SHA. If there are multiple builds in the queue, or
-you are retrying an old build, the commit to be tested needs to be within the
-git history that is cloned. Setting too small a value for `GIT_DEPTH` can make
+Since Git fetching and cloning is based on a ref, such as a branch name, Runners
+can't clone a specific commit SHA. If there are multiple jobs in the queue, or
+you are retrying an old job, the commit to be tested needs to be within the
+Git history that is cloned. Setting too small a value for `GIT_DEPTH` can make
it impossible to run these old commits. You will see `unresolved reference` in
-build logs. You should then reconsider changing `GIT_DEPTH` to a higher value.
+job logs. You should then reconsider changing `GIT_DEPTH` to a higher value.
-Builds that rely on `git describe` may not work correctly when `GIT_DEPTH` is
-set since only part of the git history is present.
+Jobs that rely on `git describe` may not work correctly when `GIT_DEPTH` is
+set since only part of the Git history is present.
To fetch or clone only the last 3 commits:
-```
+
+```yaml
variables:
GIT_DEPTH: "3"
```
@@ -959,7 +1282,7 @@ Read more about the various [YAML features](https://learnxinyminutes.com/docs/ya
> Introduced in GitLab 8.6 and GitLab Runner v1.1.1.
-YAML also has a handy feature called 'anchors', which let you easily duplicate
+YAML has a handy feature called 'anchors', which lets you easily duplicate
content across your document. Anchors can be used to duplicate/inherit
properties, and is a perfect example to be used with [hidden keys](#hidden-keys)
to provide templates for your jobs.
@@ -1084,21 +1407,55 @@ with an API call.
[Read more in the triggers documentation.](../triggers/README.md)
+### pages
+
+`pages` is a special job that is used to upload static content to GitLab that
+can be used to serve your website. It has a special syntax, so the two
+requirements below must be met:
+
+1. Any static content must be placed under a `public/` directory
+1. `artifacts` with a path to the `public/` directory must be defined
+
+The example below simply moves all files from the root of the project to the
+`public/` directory. The `.public` workaround is so `cp` doesn't also copy
+`public/` to itself in an infinite loop:
+
+```
+pages:
+ stage: deploy
+ script:
+ - mkdir .public
+ - cp -r * .public
+ - mv .public public
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
+```
+
+Read more on [GitLab Pages user documentation](../../user/project/pages/index.md).
+
## Validate the .gitlab-ci.yml
Each instance of GitLab CI has an embedded debug tool called Lint.
You can find the link under `/ci/lint` of your gitlab instance.
-## Skipping builds
+## Skipping jobs
If your commit message contains `[ci skip]` or `[skip ci]`, using any
-capitalization, the commit will be created but the builds will be skipped.
+capitalization, the commit will be created but the jobs will be skipped.
## Examples
Visit the [examples README][examples] to see a list of examples using GitLab
CI with various languages.
+[env-manual]: ../environments.md#manually-deploying-to-environments
[examples]: ../examples/README.md
[ce-6323]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6323
[environment]: ../environments.md
+[ce-6669]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6669
+[variables]: ../variables/README.md
+[ce-7983]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7983
+[ce-7447]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7447
diff --git a/doc/customization/branded_login_page/appearance.png b/doc/customization/branded_login_page/appearance.png
index 023dc5599b4..31ea4559d37 100644
--- a/doc/customization/branded_login_page/appearance.png
+++ b/doc/customization/branded_login_page/appearance.png
Binary files differ
diff --git a/doc/customization/branded_login_page/custom_sign_in.png b/doc/customization/branded_login_page/custom_sign_in.png
index 7d99e0a2b3b..c0888fe1f18 100644
--- a/doc/customization/branded_login_page/custom_sign_in.png
+++ b/doc/customization/branded_login_page/custom_sign_in.png
Binary files differ
diff --git a/doc/customization/branded_login_page/default_login_page.png b/doc/customization/branded_login_page/default_login_page.png
index 0cfa9da202e..9b1233cef45 100644
--- a/doc/customization/branded_login_page/default_login_page.png
+++ b/doc/customization/branded_login_page/default_login_page.png
Binary files differ
diff --git a/doc/customization/branded_page_and_email_header.md b/doc/customization/branded_page_and_email_header.md
new file mode 100644
index 00000000000..9a0f0b382fa
--- /dev/null
+++ b/doc/customization/branded_page_and_email_header.md
@@ -0,0 +1,15 @@
+# Changing the logo on the overall page and email header
+
+Navigate to the **Admin** area and go to the **Appearance** page.
+
+Upload the custom logo (**Header logo**) in the section **Navigation bar**.
+
+![appearance](branded_page_and_email_header/appearance.png)
+
+After saving the page, your GitLab navigation bar will contain the custom logo:
+
+![custom_brand_header](branded_page_and_email_header/custom_brand_header.png)
+
+The GitLab pipeline emails will also have the custom logo:
+
+![custom_email_header](branded_page_and_email_header/custom_email_header.png)
diff --git a/doc/customization/branded_page_and_email_header/appearance.png b/doc/customization/branded_page_and_email_header/appearance.png
new file mode 100644
index 00000000000..abbba6f9ac9
--- /dev/null
+++ b/doc/customization/branded_page_and_email_header/appearance.png
Binary files differ
diff --git a/doc/customization/branded_page_and_email_header/custom_brand_header.png b/doc/customization/branded_page_and_email_header/custom_brand_header.png
new file mode 100644
index 00000000000..7390f8a5e4e
--- /dev/null
+++ b/doc/customization/branded_page_and_email_header/custom_brand_header.png
Binary files differ
diff --git a/doc/customization/branded_page_and_email_header/custom_email_header.png b/doc/customization/branded_page_and_email_header/custom_email_header.png
new file mode 100644
index 00000000000..705698ef4a8
--- /dev/null
+++ b/doc/customization/branded_page_and_email_header/custom_email_header.png
Binary files differ
diff --git a/doc/customization/libravatar.md b/doc/customization/libravatar.md
index c46ce2ee203..9bd22d3966d 100644
--- a/doc/customization/libravatar.md
+++ b/doc/customization/libravatar.md
@@ -16,7 +16,7 @@ the configuration options as follows:
```yml
gravatar:
enabled: true
- # gravatar URLs: possible placeholders: %{hash} %{size} %{email}
+ # gravatar URLs: possible placeholders: %{hash} %{size} %{email} %{username}
plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
```
@@ -25,7 +25,7 @@ the configuration options as follows:
```yml
gravatar:
enabled: true
- # gravatar URLs: possible placeholders: %{hash} %{size} %{email}
+ # gravatar URLs: possible placeholders: %{hash} %{size} %{email} %{username}
ssl_url: "https://seccdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
```
diff --git a/doc/development/README.md b/doc/development/README.md
index 9706cb1de7f..9496a87d84d 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -8,16 +8,24 @@
## Styleguides
+- [API styleguide](api_styleguide.md) Use this styleguide if you are
+ contributing to the API.
- [Documentation styleguide](doc_styleguide.md) Use this styleguide if you are
contributing to documentation.
+- [Writing documentation](writing_documentation.md)
+ - [Distinction between general documentation and technical articles](writing_documentation.md#distinction-between-general-documentation-and-technical-articles)
- [SQL Migration Style Guide](migration_style_guide.md) for creating safe SQL migrations
- [Testing standards and style guidelines](testing.md)
-- [UI guide](ui_guide.md) for building GitLab with existing CSS styles and elements
-- [Frontend guidelines](frontend.md)
-- [SQL guidelines](sql.md) for SQL guidelines
+- [UX guide](ux_guide/index.md) for building GitLab with existing CSS styles and elements
+- [Frontend guidelines](fe_guide/index.md)
+- [SQL guidelines](sql.md) for working with SQL queries
+- [Sidekiq guidelines](sidekiq_style_guide.md) for working with Sidekiq workers
+- [`Gemfile` guidelines](gemfile.md)
## Process
+- [Generate a changelog entry with `bin/changelog`](changelog.md)
+- [Limit conflicts with EE when developing on CE](limit_ee_conflicts.md)
- [Code review guidelines](code_review.md) for reviewing code and having code reviewed.
- [Merge request performance guidelines](merge_request_performance_guidelines.md)
for ensuring merge requests do not negatively impact GitLab performance
@@ -25,7 +33,6 @@
## Backend howtos
- [Architecture](architecture.md) of GitLab
-- [CI setup](ci_setup.md) for testing GitLab
- [Gotchas](gotchas.md) to avoid
- [How to dump production data to staging](db_dump.md)
- [Instrumentation](instrumentation.md)
@@ -33,11 +40,24 @@
- [Rake tasks](rake_tasks.md) for development
- [Shell commands](shell_commands.md) in the GitLab codebase
- [Sidekiq debugging](sidekiq_debugging.md)
+- [Object state models](object_state_models.md)
+- [Building a package for testing purposes](build_test_package.md)
+- [Manage feature flags](feature_flags.md)
## Databases
- [What requires downtime?](what_requires_downtime.md)
- [Adding database indexes](adding_database_indexes.md)
+- [Post Deployment Migrations](post_deployment_migrations.md)
+- [Foreign Keys & Associations](foreign_keys.md)
+- [Serializing Data](serializing_data.md)
+- [Polymorphic Associations](polymorphic_associations.md)
+- [Single Table Inheritance](single_table_inheritance.md)
+- [Background Migrations](background_migrations.md)
+
+## i18n
+
+- [Internationalization for GitLab](i18n_guide.md)
## Compliance
diff --git a/doc/development/api_styleguide.md b/doc/development/api_styleguide.md
new file mode 100644
index 00000000000..ce444ebdde4
--- /dev/null
+++ b/doc/development/api_styleguide.md
@@ -0,0 +1,96 @@
+# API styleguide
+
+This styleguide recommends best practices for API development.
+
+## Instance variables
+
+Please do not use instance variables, there is no need for them (we don't need
+to access them as we do in Rails views), local variables are fine.
+
+## Entities
+
+Always use an [Entity] to present the endpoint's payload.
+
+## Methods and parameters description
+
+Every method must be described using the [Grape DSL](https://github.com/ruby-grape/grape#describing-methods)
+(see https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/api/environments.rb
+for a good example):
+
+- `desc` for the method summary. You should pass it a block for additional
+ details such as:
+ - The GitLab version when the endpoint was added
+ - If the endpoint is deprecated, and if so, when will it be removed
+
+- `params` for the method params. This acts as description,
+ [validation, and coercion of the parameters]
+
+A good example is as follows:
+
+```ruby
+desc 'Get all broadcast messages' do
+ detail 'This feature was introduced in GitLab 8.12.'
+ success Entities::BroadcastMessage
+end
+params do
+ optional :page, type: Integer, desc: 'Current page number'
+ optional :per_page, type: Integer, desc: 'Number of messages per page'
+end
+get do
+ messages = BroadcastMessage.all
+
+ present paginate(messages), with: Entities::BroadcastMessage
+end
+```
+
+## Declared params
+
+> Grape allows you to access only the parameters that have been declared by your
+`params` block. It filters out the params that have been passed, but are not
+allowed.
+
+– https://github.com/ruby-grape/grape#declared
+
+### Exclude params from parent namespaces!
+
+> By default `declared(params) `includes parameters that were defined in all
+parent namespaces.
+
+– https://github.com/ruby-grape/grape#include-parent-namespaces
+
+In most cases you will want to exclude params from the parent namespaces:
+
+```ruby
+declared(params, include_parent_namespaces: false)
+```
+
+### When to use `declared(params)`?
+
+You should always use `declared(params)` when you pass the params hash as
+arguments to a method call.
+
+For instance:
+
+```ruby
+# bad
+User.create(params) # imagine the user submitted `admin=1`... :)
+
+# good
+User.create(declared(params, include_parent_namespaces: false).to_h)
+```
+
+>**Note:**
+`declared(params)` return a `Hashie::Mash` object, on which you will have to
+call `.to_h`.
+
+But we can use `params[key]` directly when we access single elements.
+
+For instance:
+
+```ruby
+# good
+Model.create(foo: params[:foo])
+```
+
+[Entity]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/api/entities.rb
+[validation, and coercion of the parameters]: https://github.com/ruby-grape/grape#parameter-validation-and-coercion
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index 33fd50f4c11..54029e00507 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -4,15 +4,15 @@
There are two editions of GitLab: [Enterprise Edition](https://about.gitlab.com/gitlab-ee/) (EE) and [Community Edition](https://about.gitlab.com/gitlab-ce/) (CE). GitLab CE is delivered via git from the [gitlabhq repository](https://gitlab.com/gitlab-org/gitlab-ce/tree/master). New versions of GitLab are released in stable branches and the master branch is for bleeding edge development.
-EE releases are available not long after CE releases. To obtain the GitLab EE there is a [repository at gitlab.com](https://gitlab.com/subscribers/gitlab-ee). For more information about the release process see the section 'New versions and upgrading' in the readme.
+EE releases are available not long after CE releases. To obtain the GitLab EE there is a [repository at gitlab.com](https://gitlab.com/gitlab-org/gitlab-ee). For more information about the release process see the section 'New versions and upgrading' in the readme.
-Both EE and CE require an add-on component called gitlab-shell. It is obtained from the [gitlab-shell repository](https://gitlab.com/gitlab-org/gitlab-shell/tree/master). New versions are usually tags but staying on the master branch will give you the latest stable version. New releases are generally around the same time as GitLab CE releases with exception for informal security updates deemed critical.
+Both EE and CE require some add-on components called gitlab-shell and Gitaly. These components are available from the [gitlab-shell](https://gitlab.com/gitlab-org/gitlab-shell/tree/master) and [gitaly](https://gitlab.com/gitlab-org/gitaly/tree/master) repositories respectively. New versions are usually tags but staying on the master branch will give you the latest stable version. New releases are generally around the same time as GitLab CE releases with exception for informal security updates deemed critical.
## Physical office analogy
You can imagine GitLab as a physical office.
-**The repositories** are the goods GitLab handling.
+**The repositories** are the goods GitLab handles.
They can be stored in a warehouse.
This can be either a hard disk, or something more complex, such as a NFS filesystem;
@@ -35,8 +35,10 @@ Their job description:
- make tasks for Sidekiq;
- fetch stuff from the warehouse or move things around in there;
-**Gitlab-shell** is a third kind of worker that takes orders from a fax machine (SSH) instead of the front desk (HTTP).
-Gitlab-shell communicates with Sidekiq via the “communication board” (Redis), and asks quick questions of the Unicorn workers either directly or via the front desk.
+**GitLab-shell** is a third kind of worker that takes orders from a fax machine (SSH) instead of the front desk (HTTP).
+GitLab-shell communicates with Sidekiq via the “communication board” (Redis), and asks quick questions of the Unicorn workers either directly or via the front desk.
+
+**Gitaly** is a back desk that is specialized on reaching the disks to perform git operations efficiently and keep a copy of the result of costly operations. All git operations go through Gitaly.
**GitLab Enterprise Edition (the application)** is the collection of processes and business practices that the office is run by.
@@ -52,8 +54,8 @@ To serve repositories over SSH there's an add-on application called gitlab-shell
### Components
-![GitLab Diagram Overview](gitlab_architecture_diagram.png)
-
+<img src="https://docs.google.com/drawings/d/1fBzAyklyveF-i-2q-OHUIqDkYfjjxC4mq5shwKSZHLs/pub?w=987&amp;h=797">
+
_[edit diagram (for GitLab team members only)](https://docs.google.com/drawings/d/1fBzAyklyveF-i-2q-OHUIqDkYfjjxC4mq5shwKSZHLs/edit)_
A typical install of GitLab will be on GNU/Linux. It uses Nginx or Apache as a web front end to proxypass the Unicorn web server. By default, communication between Unicorn and the front end is via a Unix domain socket but forwarding requests via TCP is also supported. The web front end accesses `/home/git/gitlab/public` bypassing the Unicorn server to serve static pages, uploads (e.g. avatar images or attachments), and precompiled assets. GitLab serves web pages and a [GitLab API](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/api) using the Unicorn web server. It uses Sidekiq as a job queue which, in turn, uses redis as a non-persistent database backend for job information, meta data, and incoming jobs.
@@ -62,7 +64,11 @@ The GitLab web app uses MySQL or PostgreSQL for persistent database information
When serving repositories over HTTP/HTTPS GitLab utilizes the GitLab API to resolve authorization and access as well as serving git objects.
-The add-on component gitlab-shell serves repositories over SSH. It manages the SSH keys within `/home/git/.ssh/authorized_keys` which should not be manually edited. gitlab-shell accesses the bare repositories directly to serve git objects and communicates with redis to submit jobs to Sidekiq for GitLab to process. gitlab-shell queries the GitLab API to determine authorization and access.
+The add-on component gitlab-shell serves repositories over SSH. It manages the SSH keys within `/home/git/.ssh/authorized_keys` which should not be manually edited. gitlab-shell accesses the bare repositories through Gitaly to serve git objects and communicates with redis to submit jobs to Sidekiq for GitLab to process. gitlab-shell queries the GitLab API to determine authorization and access.
+
+Gitaly executes git operations from gitlab-shell and the GitLab web app, and provides an API to the GitLab web app to get attributes from git (e.g. title, branches, tags, other meta data), and to get blobs (e.g. diffs, commits, files).
+
+You may also be interested in the [production architecture of GitLab.com](https://about.gitlab.com/handbook/infrastructure/production-architecture/).
### Installation Folder Summary
@@ -188,3 +194,7 @@ bundle exec rake gitlab:check RAILS_ENV=production
```
Note: It is recommended to log into the `git` user using `sudo -i -u git` or `sudo su - git`. While the sudo commands provided by gitlabhq work in Ubuntu they do not always work in RHEL.
+
+## GitLab.com
+
+We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/handbook/infrastructure/production-architecture/) but this is probably over the top unless you have millions of users.
diff --git a/doc/development/background_migrations.md b/doc/development/background_migrations.md
new file mode 100644
index 00000000000..0239e6b3163
--- /dev/null
+++ b/doc/development/background_migrations.md
@@ -0,0 +1,205 @@
+# Background Migrations
+
+Background migrations can be used to perform data migrations that would
+otherwise take a very long time (hours, days, years, etc) to complete. For
+example, you can use background migrations to migrate data so that instead of
+storing data in a single JSON column the data is stored in a separate table.
+
+## When To Use Background Migrations
+
+In the vast majority of cases you will want to use a regular Rails migration
+instead. Background migrations should _only_ be used when migrating _data_ in
+tables that have so many rows this process would take hours when performed in a
+regular Rails migration.
+
+Background migrations _may not_ be used to perform schema migrations, they
+should only be used for data migrations.
+
+Some examples where background migrations can be useful:
+
+* Migrating events from one table to multiple separate tables.
+* Populating one column based on JSON stored in another column.
+* Migrating data that depends on the output of exernal services (e.g. an API).
+
+## Isolation
+
+Background migrations must be isolated and can not use application code (e.g.
+models defined in `app/models`). Since these migrations can take a long time to
+run it's possible for new versions to be deployed while they are still running.
+
+It's also possible for different migrations to be executed at the same time.
+This means that different background migrations should not migrate data in a
+way that would cause conflicts.
+
+## How It Works
+
+Background migrations are simple classes that define a `perform` method. A
+Sidekiq worker will then execute such a class, passing any arguments to it. All
+migration classes must be defined in the namespace
+`Gitlab::BackgroundMigration`, the files should be placed in the directory
+`lib/gitlab/background_migration/`.
+
+## Scheduling
+
+Scheduling a migration can be done in either a regular migration or a
+post-deployment migration. To do so, simply use the following code while
+replacing the class name and arguments with whatever values are necessary for
+your migration:
+
+```ruby
+BackgroundMigrationWorker.perform_async('BackgroundMigrationClassName', [arg1, arg2, ...])
+```
+
+Usually it's better to schedule jobs in bulk, for this you can use
+`BackgroundMigrationWorker.perform_bulk`:
+
+```ruby
+BackgroundMigrationWorker.perform_bulk(
+ ['BackgroundMigrationClassName', [1]],
+ ['BackgroundMigrationClassName', [2]],
+ ...
+)
+```
+
+You'll also need to make sure that newly created data is either migrated, or
+saved in both the old and new version upon creation. For complex and time
+consuming migrations it's best to schedule a background job using an
+`after_create` hook so this doesn't affect response timings. The same applies to
+updates. Removals in turn can be handled by simply defining foreign keys with
+cascading deletes.
+
+## Cleaning Up
+
+Because background migrations can take a long time you can't immediately clean
+things up after scheduling them. For example, you can't drop a column that's
+used in the migration process as this would cause jobs to fail. This means that
+you'll need to add a separate _post deployment_ migration in a future release
+that finishes any remaining jobs before cleaning things up (e.g. removing a
+column).
+
+As an example, say you want to migrate the data from column `foo` (containing a
+big JSON blob) to column `bar` (containing a string). The process for this would
+roughly be as follows:
+
+1. Release A:
+ 1. Create a migration class that perform the migration for a row with a given ID.
+ 1. Deploy the code for this release, this should include some code that will
+ schedule jobs for newly created data (e.g. using an `after_create` hook).
+ 1. Schedule jobs for all existing rows in a post-deployment migration. It's
+ possible some newly created rows may be scheduled twice so your migration
+ should take care of this.
+1. Release B:
+ 1. Deploy code so that the application starts using the new column and stops
+ scheduling jobs for newly created data.
+ 1. In a post-deployment migration you'll need to ensure no jobs remain. To do
+ so you can use `Gitlab::BackgroundMigration.steal` to process any remaining
+ jobs before continueing.
+ 1. Remove the old column.
+
+## Example
+
+To explain all this, let's use the following example: the table `services` has a
+field called `properties` which is stored in JSON. For all rows you want to
+extract the `url` key from this JSON object and store it in the `services.url`
+column. There are millions of services and parsing JSON is slow, thus you can't
+do this in a regular migration.
+
+To do this using a background migration we'll start with defining our migration
+class:
+
+```ruby
+class Gitlab::BackgroundMigration::ExtractServicesUrl
+ class Service < ActiveRecord::Base
+ self.table_name = 'services'
+ end
+
+ def perform(service_id)
+ # A row may be removed between scheduling and starting of a job, thus we
+ # need to make sure the data is still present before doing any work.
+ service = Service.select(:properties).find_by(id: service_id)
+
+ return unless service
+
+ begin
+ json = JSON.load(service.properties)
+ rescue JSON::ParserError
+ # If the JSON is invalid we don't want to keep the job around forever,
+ # instead we'll just leave the "url" field to whatever the default value
+ # is.
+ return
+ end
+
+ service.update(url: json['url']) if json['url']
+ end
+end
+```
+
+Next we'll need to adjust our code so we schedule the above migration for newly
+created and updated services. We can do this using something along the lines of
+the following:
+
+```ruby
+class Service < ActiveRecord::Base
+ after_commit :schedule_service_migration, on: :update
+ after_commit :schedule_service_migration, on: :create
+
+ def schedule_service_migration
+ BackgroundMigrationWorker.perform_async('ExtractServicesUrl', [id])
+ end
+end
+```
+
+We're using `after_commit` here to ensure the Sidekiq job is not scheduled
+before the transaction completes as doing so can lead to race conditions where
+the changes are not yet visible to the worker.
+
+Next we'll need a post-deployment migration that schedules the migration for
+existing data. Since we're dealing with a lot of rows we'll schedule jobs in
+batches instead of doing this one by one:
+
+```ruby
+class ScheduleExtractServicesUrl < ActiveRecord::Migration
+ disable_ddl_transaction!
+
+ class Service < ActiveRecord::Base
+ self.table_name = 'services'
+ end
+
+ def up
+ Service.select(:id).in_batches do |relation|
+ jobs = relation.pluck(:id).map do |id|
+ ['ExtractServicesUrl', [id]]
+ end
+
+ BackgroundMigrationWorker.perform_bulk(jobs)
+ end
+ end
+
+ def down
+ end
+end
+```
+
+Once deployed our application will continue using the data as before but at the
+same time will ensure that both existing and new data is migrated.
+
+In the next release we can remove the `after_commit` hooks and related code. We
+will also need to add a post-deployment migration that consumes any remaining
+jobs. Such a migration would look like this:
+
+```ruby
+class ConsumeRemainingExtractServicesUrlJobs < ActiveRecord::Migration
+ disable_ddl_transaction!
+
+ def up
+ Gitlab::BackgroundMigration.steal('ExtractServicesUrl')
+ end
+
+ def down
+ end
+end
+```
+
+This migration will then process any jobs for the ExtractServicesUrl migration
+and continue once all jobs have been processed. Once done you can safely remove
+the `services.properties` column.
diff --git a/doc/development/build_test_package.md b/doc/development/build_test_package.md
new file mode 100644
index 00000000000..439d228baef
--- /dev/null
+++ b/doc/development/build_test_package.md
@@ -0,0 +1,39 @@
+# Building a package for testing
+
+While developing a new feature or modifying an existing one, it is helpful if an
+installable package (or a docker image) containing those changes is available
+for testing. For this very purpose, a manual job is provided in the GitLab CI/CD
+pipeline that can be used to trigger a pipeline in the omnibus-gitlab repository
+that will create
+1. A deb package for Ubuntu 16.04, available as a build artifact, and
+2. A docker image, which is pushed to [Omnibus GitLab's container
+registry](https://gitlab.com/gitlab-org/omnibus-gitlab/container_registry)
+(images titled `gitlab-ce` and `gitlab-ee` respectively and image tag is the
+commit which triggered the pipeline).
+
+When you push a commit to either the gitlab-ce or gitlab-ee project, the
+pipeline for that commit will have a `build-package` manual action you can
+trigger.
+
+![Manual actions](img/trigger_ss1.png)
+
+![Build package manual action](img/trigger_ss2.png)
+
+## Specifying versions of components
+
+If you want to create a package from a specific branch, commit or tag of any of
+the GitLab components (like GitLab Workhorse, Gitaly, GitLab Pages, etc.), you
+can specify the branch name, commit sha or tag in the component's respective
+`*_VERSION` file. For example, if you want to build a package that uses the
+branch `0-1-stable`, modify the content of `GITALY_SERVER_VERSION` to
+`0-1-stable` and push the commit. This will create a manual job that can be
+used to trigger the build.
+
+## Specifying the branch in omnibus-gitlab repository
+
+In scenarios where a configuration change is to be introduced and omnibus-gitlab
+repository already has the necessary changes in a specific branch, you can build
+a package against that branch through an environment variable named
+`OMNIBUS_BRANCH`. To do this, specify that environment variable with the name of
+the branch as value in `.gitlab-ci.yml` and push a commit. This will create a
+manual job that can be used to trigger the build.
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
new file mode 100644
index 00000000000..ce39a379a0e
--- /dev/null
+++ b/doc/development/changelog.md
@@ -0,0 +1,251 @@
+# Changelog entries
+
+This guide contains instructions for when and how to generate a changelog entry
+file, as well as information and history about our changelog process.
+
+## Overview
+
+Each bullet point, or **entry**, in our [`CHANGELOG.md`][changelog.md] file is
+generated from a single data file in the [`changelogs/unreleased/`][unreleased]
+(or corresponding EE) folder. The file is expected to be a [YAML] file in the
+following format:
+
+```yaml
+---
+title: "Going through change[log]s"
+merge_request: 1972
+author: Ozzy Osbourne
+```
+
+The `merge_request` value is a reference to a merge request that adds this
+entry, and the `author` key is used to give attribution to community
+contributors. **Both are optional**.
+
+Community contributors and core team members are encouraged to add their name to
+the `author` field. GitLab team members **should not**.
+
+[changelog.md]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG.md
+[unreleased]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/changelogs/
+[YAML]: https://en.wikipedia.org/wiki/YAML
+
+## What warrants a changelog entry?
+
+- Any user-facing change **should** have a changelog entry. Example: "GitLab now
+ uses system fonts for all text."
+- A fix for a regression introduced and then fixed in the same release (i.e.,
+ fixing a bug introduced during a monthly release candidate) **should not**
+ have a changelog entry.
+- Any developer-facing change (e.g., refactoring, technical debt remediation,
+ test suite changes) **should not** have a changelog entry. Example: "Reduce
+ database records created during Cycle Analytics model spec."
+- _Any_ contribution from a community member, no matter how small, **may** have
+ a changelog entry regardless of these guidelines if the contributor wants one.
+ Example: "Fixed a typo on the search results page. (Jane Smith)"
+
+## Writing good changelog entries
+
+A good changelog entry should be descriptive and concise. It should explain the
+change to a reader who has _zero context_ about the change. If you have trouble
+making it both concise and descriptive, err on the side of descriptive.
+
+- **Bad:** Go to a project order.
+- **Good:** Show a user's starred projects at the top of the "Go to project"
+ dropdown.
+
+The first example provides no context of where the change was made, or why, or
+how it benefits the user.
+
+- **Bad:** Copy [some text] to clipboard.
+- **Good:** Update the "Copy to clipboard" tooltip to indicate what's being
+ copied.
+
+Again, the first example is too vague and provides no context.
+
+- **Bad:** Fixes and Improves CSS and HTML problems in mini pipeline graph and
+ builds dropdown.
+- **Good:** Fix tooltips and hover states in mini pipeline graph and builds
+ dropdown.
+
+The first example is too focused on implementation details. The user doesn't
+care that we changed CSS and HTML, they care about the _end result_ of those
+changes.
+
+- **Bad:** Strip out `nil`s in the Array of Commit objects returned from
+ `find_commits_by_message_with_elastic`
+- **Good:** Fix 500 errors caused by elasticsearch results referencing
+ garbage-collected commits
+
+The first example focuses on _how_ we fixed something, not on _what_ it fixes.
+The rewritten version clearly describes the _end benefit_ to the user (fewer 500
+errors), and _when_ (searching commits with ElasticSearch).
+
+Use your best judgement and try to put yourself in the mindset of someone
+reading the compiled changelog. Does this entry add value? Does it offer context
+about _where_ and _why_ the change was made?
+
+## How to generate a changelog entry
+
+A `bin/changelog` script is available to generate the changelog entry file
+automatically.
+
+Its simplest usage is to provide the value for `title`:
+
+```text
+$ bin/changelog 'Hey DZ, I added a feature to GitLab!'
+```
+
+The entry filename is based on the name of the current Git branch. If you run
+the command above on a branch called `feature/hey-dz`, it will generate a
+`changelogs/unreleased/feature-hey-dz.yml` file.
+
+The command will output the path of the generated file and its contents:
+
+```text
+create changelogs/unreleased/my-feature.yml
+---
+title: Hey DZ, I added a feature to GitLab!
+merge_request:
+author:
+```
+If you're working on the GitLab EE repository, the entry will be added to
+`changelogs/unreleased-ee/` instead.
+
+#### Arguments
+
+| Argument | Shorthand | Purpose |
+| ----------------- | --------- | --------------------------------------------- |
+| [`--amend`] | | Amend the previous commit |
+| [`--force`] | `-f` | Overwrite an existing entry |
+| [`--merge-request`] | `-m` | Set merge request ID |
+| [`--dry-run`] | `-n` | Don't actually write anything, just print |
+| [`--git-username`] | `-u` | Use Git user.name configuration as the author |
+| [`--help`] | `-h` | Print help message |
+
+[`--amend`]: #-amend
+[`--force`]: #-force-or-f
+[`--merge-request`]: #-merge-request-or-m
+[`--dry-run`]: #-dry-run-or-n
+[`--git-username`]: #-git-username-or-u
+[`--help`]: #-help
+
+##### `--amend`
+
+You can pass the **`--amend`** argument to automatically stage the generated
+file and amend it to the previous commit.
+
+If you use **`--amend`** and don't provide a title, it will automatically use
+the "subject" of the previous commit, which is the first line of the commit
+message:
+
+```text
+$ git show --oneline
+ab88683 Added an awesome new feature to GitLab
+
+$ bin/changelog --amend
+create changelogs/unreleased/feature-hey-dz.yml
+---
+title: Added an awesome new feature to GitLab
+merge_request:
+author:
+```
+
+##### `--force` or `-f`
+
+Use **`--force`** or **`-f`** to overwrite an existing changelog entry if it
+already exists.
+
+```text
+$ bin/changelog 'Hey DZ, I added a feature to GitLab!'
+error changelogs/unreleased/feature-hey-dz.yml already exists! Use `--force` to overwrite.
+
+$ bin/changelog 'Hey DZ, I added a feature to GitLab!' --force
+create changelogs/unreleased/feature-hey-dz.yml
+---
+title: Hey DZ, I added a feature to GitLab!
+merge_request: 1983
+author:
+```
+
+##### `--merge-request` or `-m`
+
+Use the **`--merge-request`** or **`-m`** argument to provide the
+`merge_request` value:
+
+```text
+$ bin/changelog 'Hey DZ, I added a feature to GitLab!' -m 1983
+create changelogs/unreleased/feature-hey-dz.yml
+---
+title: Hey DZ, I added a feature to GitLab!
+merge_request: 1983
+author:
+```
+
+##### `--dry-run` or `-n`
+
+Use the **`--dry-run`** or **`-n`** argument to prevent actually writing or
+committing anything:
+
+```text
+$ bin/changelog --amend --dry-run
+create changelogs/unreleased/feature-hey-dz.yml
+---
+title: Added an awesome new feature to GitLab
+merge_request:
+author:
+
+$ ls changelogs/unreleased/
+```
+
+##### `--git-username` or `-u`
+
+Use the **`--git-username`** or **`-u`** argument to automatically fill in the
+`author` value with your configured Git `user.name` value:
+
+```text
+$ git config user.name
+Jane Doe
+
+$ bin/changelog -u 'Hey DZ, I added a feature to GitLab!'
+create changelogs/unreleased/feature-hey-dz.yml
+---
+title: Hey DZ, I added a feature to GitLab!
+merge_request:
+author: Jane Doe
+```
+
+### History and Reasoning
+
+Our `CHANGELOG` file was previously updated manually by each contributor that
+felt their change warranted an entry. When two merge requests added their own
+entries at the same spot in the list, it created a merge conflict in one as soon
+as the other was merged. When we had dozens of merge requests fighting for the
+same changelog entry location, this quickly became a major source of merge
+conflicts and delays in development.
+
+This led us to a [boring solution] of "add your entry in a random location in
+the list." This actually worked pretty well as we got further along in each
+monthly release cycle, but at the start of a new cycle, when a new version
+section was added and there were fewer places to "randomly" add an entry, the
+conflicts became a problem again until we had a sufficient number of entries.
+
+On top of all this, it created an entirely different headache for [release managers]
+when they cherry-picked a commit into a stable branch for a patch release. If
+the commit included an entry in the `CHANGELOG`, it would include the entire
+changelog for the latest version in `master`, so the release manager would have
+to manually remove the later entries. They often would have had to do this
+multiple times per patch release. This was compounded when we had to release
+multiple patches at once due to a security issue.
+
+We needed to automate all of this manual work. So we [started brainstorming].
+After much discussion we settled on the current solution of one file per entry,
+and then compiling the entries into the overall `CHANGELOG.md` file during the
+[release process].
+
+[boring solution]: https://about.gitlab.com/handbook/#boring-solutions
+[release managers]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/release-manager.md
+[started brainstorming]: https://gitlab.com/gitlab-org/gitlab-ce/issues/17826
+[release process]: https://gitlab.com/gitlab-org/release-tools
+
+---
+
+[Return to Development documentation](README.md)
diff --git a/doc/development/ci_setup.md b/doc/development/ci_setup.md
deleted file mode 100644
index 2f49b3564ab..00000000000
--- a/doc/development/ci_setup.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# CI setup
-
-This document describes what services we use for testing GitLab and GitLab CI.
-
-We currently use three CI services to test GitLab:
-
-1. GitLab CI on [GitHost.io](https://gitlab-ce.githost.io/projects/4/) for the [GitLab.com repo](https://gitlab.com/gitlab-org/gitlab-ce)
-2. GitLab CI at ci.gitlab.org to test the private GitLab B.V. repo at dev.gitlab.org
-3. [Semephore](https://semaphoreapp.com/gitlabhq/gitlabhq/) for [GitHub.com repo](https://github.com/gitlabhq/gitlabhq)
-
-| Software @ configuration being tested | GitLab CI (ci.gitlab.org) | GitLab CI (GitHost.io) | Semaphore |
-|---------------------------------------|---------------------------|---------------------------------------------------------------------------|-----------|
-| GitLab CE @ MySQL | ✓ | ✓ [Core team can trigger builds](https://gitlab-ce.githost.io/projects/4) | |
-| GitLab CE @ PostgreSQL | | | ✓ [Core team can trigger builds](https://semaphoreapp.com/gitlabhq/gitlabhq/branches/master) |
-| GitLab EE @ MySQL | ✓ | | |
-| GitLab CI @ MySQL | ✓ | | |
-| GitLab CI @ PostgreSQL | | | ✓ |
-| GitLab CI Runner | ✓ | | ✓ |
-| GitLab Shell | ✓ | | ✓ |
-| GitLab Shell | ✓ | | ✓ |
-
-Core team has access to trigger builds if needed for GitLab CE.
-
-We use [these build scripts](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml) for testing with GitLab CI.
-
-# Build configuration on [Semaphore](https://semaphoreapp.com/gitlabhq/gitlabhq/) for testing the [GitHub.com repo](https://github.com/gitlabhq/gitlabhq)
-
-- Language: Ruby
-- Ruby version: 2.1.8
-- database.yml: pg
-
-Build commands
-
-```bash
-sudo apt-get install cmake libicu-dev -y (Setup)
-bundle install --deployment --path vendor/bundle (Setup)
-cp config/gitlab.yml.example config/gitlab.yml (Setup)
-bundle exec rake db:create (Setup)
-bundle exec rake spinach (Thread #1)
-bundle exec rake spec (thread #2)
-bundle exec rake rubocop (thread #3)
-bundle exec rake brakeman (thread #4)
-bundle exec rake jasmine:ci (thread #5)
-```
-
-Use rubygems mirror.
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index c5c23b5c0b8..4ed89146072 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -1,5 +1,27 @@
# Code Review Guidelines
+## Getting your merge request reviewed, approved, and merged
+
+There are a few rules to get your merge request accepted:
+
+1. Your merge request should only be **merged by a [maintainer][team]**.
+ 1. If your merge request includes only backend changes [^1], it must be
+ **approved by a [backend maintainer][projects]**.
+ 1. If your merge request includes only frontend changes [^1], it must be
+ **approved by a [frontend maintainer][projects]**.
+ 1. If your merge request includes frontend and backend changes [^1], it must
+ be **approved by a [frontend and a backend maintainer][projects]**.
+1. To lower the amount of merge requests maintainers need to review, you can
+ ask or assign any [reviewers][projects] for a first review.
+ 1. If you need some guidance (e.g. it's your first merge request), feel free
+ to ask one of the [Merge request coaches][team].
+ 1. The reviewer will assign the merge request to a maintainer once the
+ reviewer is satisfied with the state of the merge request.
+
+For more guidance, see [CONTRIBUTING.md](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md).
+
+## Best practices
+
This guide contains advice and best practices for performing code review, and
having your code reviewed.
@@ -9,10 +31,10 @@ code is effective, understandable, and maintainable.
Any developer can, and is encouraged to, perform code review on merge requests
of colleagues and contributors. However, the final decision to accept a merge
-request is up to one of our merge request "endbosses", denoted on the
-[team page](https://about.gitlab.com/team).
+request is up to one the project's maintainers, denoted on the
+[engineering projects][projects].
-## Everyone
+### Everyone
- Accept that many programming decisions are opinions. Discuss tradeoffs, which
you prefer, and reach a resolution quickly.
@@ -31,8 +53,11 @@ request is up to one of our merge request "endbosses", denoted on the
- Consider one-on-one chats or video calls if there are too many "I didn't
understand" or "Alternative solution:" comments. Post a follow-up comment
summarizing one-on-one discussion.
+- If you ask a question to a specific person, always start the comment by
+ mentioning them; this will ensure they see it if their notification level is
+ set to "mentioned" and other people will understand they don't have to respond.
-## Having your code reviewed
+### Having your code reviewed
Please keep in mind that code review is a process that can take multiple
iterations, and reviewers may spot things later that they may not have seen the
@@ -50,11 +75,12 @@ first time.
- Extract unrelated changes and refactorings into future merge requests/issues.
- Seek to understand the reviewer's perspective.
- Try to respond to every comment.
+- Let the reviewer select the "Resolve discussion" buttons.
- Push commits based on earlier rounds of feedback as isolated commits to the
branch. Do not squash until the branch is ready to merge. Reviewers should be
able to read individual updates based on their earlier feedback.
-## Reviewing code
+### Reviewing code
Understand why the change is necessary (fixes a bug, improves the user
experience, refactors the existing code). Then:
@@ -69,12 +95,45 @@ experience, refactors the existing code). Then:
someone else would be confused by it as well.
- After a round of line notes, it can be helpful to post a summary note such as
"LGTM :thumbsup:", or "Just a couple things to address."
-- Avoid accepting a merge request before the build succeeds. Of course, "Merge
- When Build Succeeds" (MWBS) is fine.
-- If you set the MR to "Merge When Build Succeeds", you should take over
+- Assign the merge request to the author if changes are required following your
+ review.
+- Set the milestone before merging a merge request.
+- Avoid accepting a merge request before the job succeeds. Of course, "Merge
+ When Pipeline Succeeds" (MWPS) is fine.
+- If you set the MR to "Merge When Pipeline Succeeds", you should take over
subsequent revisions for anything that would be spotted after that.
-
-## Credits
+- Consider using the [Squash and
+ merge][squash-and-merge] feature when the merge request has a lot of commits.
+
+[squash-and-merge]: https://docs.gitlab.com/ee/user/project/merge_requests/squash_and_merge.html#squash-and-merge
+
+### The right balance
+
+One of the most difficult things during code review is finding the right
+balance in how deep the reviewer can interfere with the code created by a
+reviewee.
+
+- Learning how to find the right balance takes time; that is why we have
+ reviewers that become maintainers after some time spent on reviewing merge
+ requests.
+- Finding bugs and improving code style is important, but thinking about good
+ design is important as well. Building abstractions and good design is what
+ makes it possible to hide complexity and makes future changes easier.
+- Asking the reviewee to change the design sometimes means the complete rewrite
+ of the contributed code. It's usually a good idea to ask another maintainer or
+ reviewer before doing it, but have the courage to do it when you believe it is
+ important.
+- There is a difference in doing things right and doing things right now.
+ Ideally, we should do the former, but in the real world we need the latter as
+ well. A good example is a security fix which should be released as soon as
+ possible. Asking the reviewee to do the major refactoring in the merge
+ request that is an urgent fix should be avoided.
+- Doing things well today is usually better than doing something perfectly
+ tomorrow. Shipping a kludge today is usually worse than doing something well
+ tomorrow. When you are not able to find the right balance, ask other people
+ about their opinion.
+
+### Credits
Largely based on the [thoughtbot code review guide].
@@ -83,3 +142,6 @@ Largely based on the [thoughtbot code review guide].
---
[Return to Development documentation](README.md)
+
+[projects]: https://about.gitlab.com/handbook/engineering/projects/
+[team]: https://about.gitlab.com/team/
diff --git a/doc/development/doc_styleguide.md b/doc/development/doc_styleguide.md
index 39b801f761d..5b09f79f143 100644
--- a/doc/development/doc_styleguide.md
+++ b/doc/development/doc_styleguide.md
@@ -3,6 +3,8 @@
This styleguide recommends best practices to improve documentation and to keep
it organized and easy to find.
+See also [writing documentation](writing_documentation.md).
+
## Location and naming of documents
>**Note:**
@@ -27,6 +29,8 @@ The table below shows what kind of documentation goes where.
| `doc/legal/` | Legal documents about contributing to GitLab. |
| `doc/install/`| Probably the most visited directory, since `installation.md` is there. Ideally this should go under `doc/administration/`, but it's best to leave it as-is in order to avoid confusion (still debated though). |
| `doc/update/` | Same with `doc/install/`. Should be under `administration/`, but this is a well known location, better leave as-is, at least for now. |
+| `doc/topics/` | Indexes per Topic (`doc/topics/topic-name/index.md`): all resources for that topic (user and admin documentation, articles, and third-party docs) |
+| `doc/articles/` | [Technical Articles](writing_documentation.md#technical-articles): user guides, admin guides, technical overviews, tutorials (`doc/articles/article-title/index.md`). |
---
@@ -56,6 +60,10 @@ The table below shows what kind of documentation goes where.
own document located at `doc/user/admin_area/settings/`. For example,
the **Visibility and Access Controls** category should have a document
located at `doc/user/admin_area/settings/visibility_and_access_controls.md`.
+1. The `doc/topics/` directory holds topic-related technical content. Create
+ `doc/topics/topic-name/subtopic-name/index.md` when subtopics become necessary.
+ General user- and admin- related documentation, should be placed accordingly.
+1. For technical articles, place their images under `doc/articles/article-title/img/`.
---
@@ -93,12 +101,14 @@ merge request.
links shift too, which eventually leads to dead links. If you think it is
compelling to add numbers in headings, make sure to at least discuss it with
someone in the Merge Request
+- Avoid adding things that show ephemeral statuses. For example, if a feature is
+ considered beta or experimental, put this info in a note, not in the heading.
- When introducing a new document, be careful for the headings to be
grammatically and syntactically correct. It is advised to mention one or all
- of the following GitLab members for a review: `@axil`, `@rspeicher`,
- `@dblessing`, `@ashleys`. This is to ensure that no document
- with wrong heading is going live without an audit, thus preventing dead links
- and redirection issues when corrected
+ of the following GitLab members for a review: `@axil`, `@rspeicher`, `@marcia`,
+ `@SeanPackham`. This is to ensure that no document with wrong heading is going
+ live without an audit, thus preventing dead links and redirection issues when
+ corrected
- Leave exactly one newline after a heading
## Links
@@ -111,16 +121,94 @@ merge request.
add an alternative text: `[identifier]: https://example.com "Alternative text"`
that appears when hovering your mouse on a link
+### Linking to inline docs
+
+Sometimes it's needed to link to the built-in documentation that GitLab provides
+under `/help`. This is normally done in files inside the `app/views/` directory
+with the help of the `help_page_path` helper method.
+
+In its simplest form, the HAML code to generate a link to the `/help` page is:
+
+```haml
+= link_to 'Help page', help_page_path('user/permissions')
+```
+
+The `help_page_path` contains the path to the document you want to link to with
+the following conventions:
+
+- it is relative to the `doc/` directory in the GitLab repository
+- the `.md` extension must be omitted
+- it must not end with a slash (`/`)
+
+Below are some special cases where should be used depending on the context.
+You can combine one or more of the following:
+
+1. **Linking to an anchor link.** Use `anchor` as part of the `help_page_path`
+ method:
+
+ ```haml
+ = link_to 'Help page', help_page_path('user/permissions', anchor: 'anchor-link')
+ ```
+
+1. **Opening links in a new tab.** This should be the default behavior:
+
+ ```haml
+ = link_to 'Help page', help_page_path('user/permissions'), target: '_blank'
+ ```
+
+1. **Linking to a circle icon.** Usually used in settings where a long
+ description cannot be used, like near checkboxes. You can basically use
+ any font awesome icon, but prefer the `question-circle`:
+
+ ```haml
+ = link_to icon('question-circle'), help_page_path('user/permissions')
+ ```
+
+1. **Using a button link.** Useful in places where text would be out of context
+ with the rest of the page layout:
+
+ ```haml
+ = link_to 'Help page', help_page_path('user/permissions'), class: 'btn btn-info'
+ ```
+
+1. **Underlining a link.**
+
+ ```haml
+ = link_to 'Help page', help_page_path('user/permissions'), class: 'underlined-link'
+ ```
+
+1. **Using links inline of some text.**
+
+ ```haml
+ Description to #{link_to 'Help page', help_page_path('user/permissions')}.
+ ```
+
+1. **Adding a period at the end of the sentence.** Useful when you don't want
+ the period to be part of the link:
+
+ ```haml
+ = succeed '.' do
+ Learn more in the
+ = link_to 'Help page', help_page_path('user/permissions')
+ ```
+
## Images
- Place images in a separate directory named `img/` in the same directory where
the `.md` document that you're working on is located. Always prepend their
names with the name of the document that they will be included in. For
example, if there is a document called `twitter.md`, then a valid image name
- could be `twitter_login_screen.png`.
+ could be `twitter_login_screen.png`. [**Exception**: images for
+ [articles](writing_documentation.md#technical-articles) should be
+ put in a directory called `img` underneath `/articles/article_title/img/`, therefore,
+ there's no need to prepend the document name to their filenames.]
- Images should have a specific, non-generic name that will differentiate them.
- Keep all file names in lower case.
- Consider using PNG images instead of JPEG.
+- Compress all images with <https://tinypng.com/> or similar tool.
+- Compress gifs with <https://ezgif.com/optimize> or similar toll.
+- Images should be used (only when necessary) to _illustrate_ the description
+of a process, not to _replace_ it.
Inside the document:
@@ -314,17 +402,34 @@ In this case:
- different highlighting languages are used for each config in the code block
- the [references](#references) guide is used for reconfigure/restart
+## Fake tokens
+
+There may be times where a token is needed to demonstrate an API call using
+cURL or a secret variable used in CI. It is strongly advised not to use real
+tokens in documentation even if the probability of a token being exploited is
+low.
+
+You can use the following fake tokens as examples.
+
+| **Token type** | **Token value** |
+| --------------------- | --------------------------------- |
+| Private user token | `9koXpg98eAheJpvBs5tK` |
+| Personal access token | `n671WNGecHugsdEDPsyo` |
+| Application ID | `2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6` |
+| Application secret | `04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df` |
+| Secret CI variable | `Li8j-mLUVA3eZYjPfd_H` |
+| Specific Runner token | `yrnZW46BrtBFqM7xDzE7dddd` |
+| Shared Runner token | `6Vk7ZsosqQyfreAxXTZr` |
+| Trigger token | `be20d8dcc028677c931e04f3871a9b` |
+| Webhook secret token | `6XhDroRcYPM5by_h-HLY` |
+| Health check token | `Tu7BgjR9qeZTEyRzGG2P` |
+| Request profile token | `7VgpS4Ax5utVD2esNstz` |
+
## API
Here is a list of must-have items. Use them in the exact order that appears
on this document. Further explanation is given below.
-- Every method must be described using [Grape's DSL](https://github.com/ruby-grape/grape/tree/v0.13.0#describing-methods)
- (see https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/api/environments.rb
- for a good example):
- - `desc` for the method summary (you can pass it a block for additional details)
- - `params` for the method params (this acts as description **and** validation
- of the params)
- Every method must have the REST API request. For example:
```
@@ -354,7 +459,7 @@ Rendered example:
### cURL commands
-- Use `https://gitlab.example.com/api/v3/` as an endpoint.
+- Use `https://gitlab.example.com/api/v4/` as an endpoint.
- Wherever needed use this private token: `9koXpg98eAheJpvBs5tK`.
- Always put the request first. `GET` is the default so you don't have to
include it.
@@ -378,7 +483,7 @@ Below is a set of [cURL][] examples that you can use in the API documentation.
Get the details of a group:
```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/gitlab-org
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/gitlab-org
```
#### cURL example with parameters passed in the URL
@@ -386,7 +491,7 @@ curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/a
Create a new project under the authenticated user's namespace:
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects?name=foo"
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects?name=foo"
```
#### Post data using cURL's --data
@@ -396,7 +501,7 @@ cURL's `--data` option. The example below will create a new project `foo` under
the authenticated user's namespace.
```bash
-curl --data "name=foo" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects"
+curl --data "name=foo" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects"
```
#### Post data using JSON content
@@ -405,7 +510,7 @@ curl --data "name=foo" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://g
and double quotes.
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "Content-Type: application/json" --data '{"path": "my-group", "name": "My group"}' https://gitlab.example.com/api/v3/groups
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "Content-Type: application/json" --data '{"path": "my-group", "name": "My group"}' https://gitlab.example.com/api/v4/groups
```
#### Post data using form-data
@@ -414,7 +519,7 @@ Instead of using JSON or urlencode you can use multipart/form-data which
properly handles data encoding:
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "title=ssh-key" --form "key=ssh-rsa AAAAB3NzaC1yc2EA..." https://gitlab.example.com/api/v3/users/25/keys
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "title=ssh-key" --form "key=ssh-rsa AAAAB3NzaC1yc2EA..." https://gitlab.example.com/api/v4/users/25/keys
```
The above example is run by and administrator and will add an SSH public key
@@ -428,7 +533,7 @@ contains spaces in its title. Observe how spaces are escaped using the `%20`
ASCII code.
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/42/issues?title=Hello%20Dude"
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/42/issues?title=Hello%20Dude"
```
Use `%2F` for slashes (`/`).
@@ -440,12 +545,13 @@ restrict the sign-up e-mail domains of a GitLab instance to `*.example.com` and
`example.net`, you would do something like this:
```bash
-curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "domain_whitelist[]=*.example.com" --data "domain_whitelist[]=example.net" https://gitlab.example.com/api/v3/application/settings
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "domain_whitelist[]=*.example.com" --data "domain_whitelist[]=example.net" https://gitlab.example.com/api/v4/application/settings
```
[cURL]: http://curl.haxx.se/ "cURL website"
[single spaces]: http://www.slate.com/articles/technology/technology/2011/01/space_invaders.html
[gfm]: http://docs.gitlab.com/ce/user/markdown.html#newlines "GitLab flavored markdown documentation"
+[ce-1242]: https://gitlab.com/gitlab-org/gitlab-ce/issues/1242
[doc-restart]: ../administration/restart_gitlab.md "GitLab restart documentation"
[ce-3349]: https://gitlab.com/gitlab-org/gitlab-ce/issues/3349 "Documentation restructure"
[graffle]: https://gitlab.com/gitlab-org/gitlab-design/blob/d8d39f4a87b90fb9ae89ca12dc565347b4900d5e/production/resources/gitlab-map.graffle
diff --git a/doc/development/fe_guide/accessibility.md b/doc/development/fe_guide/accessibility.md
new file mode 100644
index 00000000000..366b220cbb2
--- /dev/null
+++ b/doc/development/fe_guide/accessibility.md
@@ -0,0 +1,13 @@
+# Accessibility
+
+## Resources
+
+[Chrome Accessibility Developer Tools][chrome-accessibility-developer-tools]
+are useful for testing for potential accessibility problems in GitLab.
+
+Accessibility best-practices and more in-depth information is available on
+[the Audit Rules page][audit-rules] for the Chrome Accessibility Developer Tools.
+
+
+[chrome-accessibility-developer-tools]: https://github.com/GoogleChrome/accessibility-developer-tools
+[audit-rules]: https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules
diff --git a/doc/development/fe_guide/architecture.md b/doc/development/fe_guide/architecture.md
new file mode 100644
index 00000000000..aebb22caa15
--- /dev/null
+++ b/doc/development/fe_guide/architecture.md
@@ -0,0 +1,22 @@
+# Architecture
+
+When you are developing a new feature that requires architectural design, or if
+you are changing the fundamental design of an existing feature, make sure it is
+discussed with one of the Frontend Architecture Experts.
+
+A Frontend Architect is an expert who makes high-level Frontend design decisions
+and decides on technical standards, including coding standards and frameworks.
+
+Architectural decisions should be accessible to everyone, so please document
+them in the relevant Merge Request discussion or by updating our documentation
+when appropriate.
+
+You can find the Frontend Architecture experts on the [team page][team-page].
+
+## Examples
+
+You can find documentation about the desired architecture for a new feature
+built with Vue.js [here][vue-section].
+
+[team-page]: https://about.gitlab.com/team
+[vue-section]: vue.md#frontend.html#how-to-build-a-new-feature-with-vue-js
diff --git a/doc/development/fe_guide/design_patterns.md b/doc/development/fe_guide/design_patterns.md
new file mode 100644
index 00000000000..e05887a19af
--- /dev/null
+++ b/doc/development/fe_guide/design_patterns.md
@@ -0,0 +1,78 @@
+# Design Patterns
+
+## Singletons
+
+When exactly one object is needed for a given task, prefer to define it as a
+`class` rather than as an object literal. Prefer also to explicitly restrict
+instantiation, unless flexibility is important (e.g. for testing).
+
+```javascript
+// bad
+
+const MyThing = {
+ prop1: 'hello',
+ method1: () => {}
+};
+
+export default MyThing;
+
+// good
+
+class MyThing {
+ constructor() {
+ this.prop1 = 'hello';
+ }
+ method1() {}
+}
+
+export default new MyThing();
+
+// best
+
+export default class MyThing {
+ constructor() {
+ if (!this.prototype.singleton) {
+ this.init();
+ this.prototype.singleton = this;
+ }
+ return this.prototype.singleton;
+ }
+
+ init() {
+ this.prop1 = 'hello';
+ }
+
+ method1() {}
+}
+
+```
+
+## Manipulating the DOM in a JS Class
+
+When writing a class that needs to manipulate the DOM guarantee a container option is provided.
+This is useful when we need that class to be instantiated more than once in the same page.
+
+Bad:
+```javascript
+class Foo {
+ constructor() {
+ document.querySelector('.bar');
+ }
+}
+new Foo();
+```
+
+Good:
+```javascript
+class Foo {
+ constructor(opts) {
+ document.querySelector(`${opts.container} .bar`);
+ }
+}
+
+new Foo({ container: '.my-element' });
+```
+You can find an example of the above in this [class][container-class-example];
+
+
+[container-class-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/mini_pipeline_graph_dropdown.js
diff --git a/doc/development/fe_guide/droplab/droplab.md b/doc/development/fe_guide/droplab/droplab.md
new file mode 100644
index 00000000000..112ff3419d9
--- /dev/null
+++ b/doc/development/fe_guide/droplab/droplab.md
@@ -0,0 +1,258 @@
+# DropLab
+
+A generic dropdown for all of your custom dropdown needs.
+
+## Usage
+
+DropLab can be used by simply adding a `data-dropdown-trigger` HTML attribute.
+This attribute allows us to find the "trigger" _(toggle)_ for the dropdown,
+whether that is a button, link or input.
+
+The value of the `data-dropdown-trigger` should be a CSS selector that
+DropLab can use to find the trigger's dropdown list.
+
+You should also add the `data-dropdown` attribute to declare the dropdown list.
+The value is irrelevant.
+
+The DropLab class has no side effects, so you must always call `.init` when
+the DOM is ready. `DropLab.prototype.init` takes the same arguments as `DropLab.prototype.addHook`.
+If you do not provide any arguments, it will globally query and instantiate all droplab compatible dropdowns.
+
+```html
+<a href="#" data-dropdown-trigger="#list">Toggle</a>
+
+<ul id="list" data-dropdown>
+ <!-- ... -->
+<ul>
+```
+```js
+const droplab = new DropLab();
+droplab.init();
+```
+
+As you can see, we have a "Toggle" link, that is declared as a trigger.
+It provides a selector to find the dropdown list it should control.
+
+### Static data
+
+You can add static list items.
+
+```html
+<a href="#" data-dropdown-trigger="#list">Toggle</a>
+
+<ul id="list" data-dropdown>
+ <li>Static value 1</li>
+ <li>Static value 2</li>
+<ul>
+```
+```js
+const droplab = new DropLab();
+droplab.init();
+```
+
+### Explicit instantiation
+
+You can pass the trigger and list elements as constructor arguments to return
+a non-global instance of DropLab using the `DropLab.prototype.init` method.
+
+```html
+<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a>
+
+<ul id="list" data-dropdown>
+ <!-- ... -->
+<ul>
+```
+```js
+const trigger = document.getElementById('trigger');
+const list = document.getElementById('list');
+
+const droplab = new DropLab();
+droplab.init(trigger, list);
+```
+
+You can also add hooks to an existing DropLab instance using `DropLab.prototype.addHook`.
+
+```html
+<a href="#" data-dropdown-trigger="#auto-dropdown">Toggle</a>
+<ul id="auto-dropdown" data-dropdown><!-- ... --><ul>
+
+<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a>
+<ul id="list" data-dropdown><!-- ... --><ul>
+```
+```js
+const droplab = new DropLab();
+
+droplab.init();
+
+const trigger = document.getElementById('trigger');
+const list = document.getElementById('list');
+
+droplab.addHook(trigger, list);
+```
+
+
+### Dynamic data
+
+Adding `data-dynamic` to your dropdown element will enable dynamic list rendering.
+
+You can template a list item using the keys of the data object provided.
+Use the handlebars syntax `{{ value }}` to HTML escape the value.
+Use the `<%= value %>` syntax to simply interpolate the value.
+Use the `<%= value %>` syntax to evaluate the value.
+
+Passing an array of objects to `DropLab.prototype.addData` will render that data
+for all `data-dynamic` dropdown lists tracked by that DropLab instance.
+
+```html
+<a href="#" data-dropdown-trigger="#list">Toggle</a>
+
+<ul id="list" data-dropdown data-dynamic>
+ <li><a href="#" data-id="{{id}}">{{text}}</a></li>
+</ul>
+```
+```js
+const droplab = new DropLab();
+
+droplab.init().addData([{
+ id: 0,
+ text: 'Jacob',
+}, {
+ id: 1,
+ text: 'Jeff',
+}]);
+```
+
+Alternatively, you can specify a specific dropdown to add this data to but passing
+the data as the second argument and and the `id` of the trigger element as the first argument.
+
+```html
+<a href="#" data-dropdown-trigger="#list" id="trigger">Toggle</a>
+
+<ul id="list" data-dropdown data-dynamic>
+ <li><a href="#" data-id="{{id}}">{{text}}</a></li>
+</ul>
+```
+```js
+const droplab = new DropLab();
+
+droplab.init().addData('trigger', [{
+ id: 0,
+ text: 'Jacob',
+}, {
+ id: 1,
+ text: 'Jeff',
+}]);
+```
+
+This allows you to mix static and dynamic content with ease, even with one trigger.
+
+Note the use of scoping regarding the `data-dropdown` attribute to capture both
+dropdown lists, one of which is dynamic.
+
+```html
+<input id="trigger" data-dropdown-trigger="#list">
+<div id="list" data-dropdown>
+ <ul>
+ <li><a href="#">Static item 1</a></li>
+ <li><a href="#">Static item 2</a></li>
+ </ul>
+ <ul data-dynamic>
+ <li><a href="#" data-id="{{id}}">{{text}}</a></li>
+ </ul>
+</div>
+```
+```js
+const droplab = new DropLab();
+
+droplab.init().addData('trigger', [{
+ id: 0,
+ text: 'Jacob',
+}, {
+ id: 1,
+ text: 'Jeff',
+}]);
+```
+
+## Internal selectors
+
+DropLab adds some CSS classes to help lower the barrier to integration.
+
+For example,
+
+* The `droplab-item-selected` css class is added to items that have been selected
+either by a mouse click or by enter key selection.
+* The `droplab-item-active` css class is added to items that have been selected
+using arrow key navigation.
+* You can add the `droplab-item-ignore` css class to any item that you do not want to be selectable. For example,
+an `<li class="divider"></li>` list divider element that should not be interactive.
+
+## Internal events
+
+DropLab uses some custom events to help lower the barrier to integration.
+
+For example,
+
+* The `click.dl` event is fired when an `li` list item has been clicked. It is also
+fired when a list item has been selected with the keyboard. It is also fired when a
+`HookButton` button is clicked (a registered `button` tag or `a` tag trigger).
+* The `input.dl` event is fired when a `HookInput` (a registered `input` tag trigger) triggers an `input` event.
+* The `mousedown.dl` event is fired when a `HookInput` triggers a `mousedown` event.
+* The `keyup.dl` event is fired when a `HookInput` triggers a `keyup` event.
+* The `keydown.dl` event is fired when a `HookInput` triggers a `keydown` event.
+
+These custom events add a `detail` object to the vanilla `Event` object that provides some potentially useful data.
+
+## Plugins
+
+Plugins are objects that are registered to be executed when a hook is added (when a droplab trigger and dropdown are instantiated).
+
+If no modules API is detected, the library will fall back as it does with `window.DropLab` and will add `window.DropLab.plugins.PluginName`.
+
+### Usage
+
+To use plugins, you can pass them in an array as the third argument of `DropLab.prototype.init` or `DropLab.prototype.addHook`.
+Some plugins require configuration values, the config object can be passed as the fourth argument.
+
+```html
+<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a>
+<ul id="list" data-dropdown><!-- ... --><ul>
+```
+```js
+const droplab = new DropLab();
+
+const trigger = document.getElementById('trigger');
+const list = document.getElementById('list');
+
+droplab.init(trigger, list, [droplabAjax], {
+ droplabAjax: {
+ endpoint: '/some-endpoint',
+ method: 'setData',
+ },
+});
+```
+
+### Documentation
+
+* [Ajax plugin](plugins/ajax.md)
+* [Filter plugin](plugins/filter.md)
+* [InputSetter plugin](plugins/input_setter.md)
+
+### Development
+
+When plugins are initialised for a droplab trigger+dropdown, DropLab will
+call the plugins `init` function, so this must be implemented in the plugin.
+
+```js
+class MyPlugin {
+ static init() {
+ this.someProp = 'someProp';
+ this.someMethod();
+ }
+
+ static someMethod() {
+ this.otherProp = 'otherProp';
+ }
+}
+
+export default MyPlugin;
+```
diff --git a/doc/development/fe_guide/droplab/plugins/ajax.md b/doc/development/fe_guide/droplab/plugins/ajax.md
new file mode 100644
index 00000000000..9c7e56fa448
--- /dev/null
+++ b/doc/development/fe_guide/droplab/plugins/ajax.md
@@ -0,0 +1,37 @@
+# Ajax
+
+`Ajax` is a droplab plugin that allows for retrieving and rendering list data from a server.
+
+## Usage
+
+Add the `Ajax` object to the plugins array of a `DropLab.prototype.init` or `DropLab.prototype.addHook` call.
+
+`Ajax` requires 2 config values, the `endpoint` and `method`.
+
+* `endpoint` should be a URL to the request endpoint.
+* `method` should be `setData` or `addData`.
+* `setData` completely replaces the dropdown with the response data.
+* `addData` appends the response data to the current dropdown list.
+
+```html
+<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a>
+<ul id="list" data-dropdown><!-- ... --><ul>
+```
+```js
+ const droplab = new DropLab();
+
+ const trigger = document.getElementById('trigger');
+ const list = document.getElementById('list');
+
+ droplab.addHook(trigger, list, [Ajax], {
+ Ajax: {
+ endpoint: '/some-endpoint',
+ method: 'setData',
+ },
+ });
+```
+
+Optionally you can set `loadingTemplate` to a HTML string. This HTML string will
+replace the dropdown list whilst the request is pending.
+
+Additionally, you can set `onError` to a function to catch any XHR errors.
diff --git a/doc/development/fe_guide/droplab/plugins/filter.md b/doc/development/fe_guide/droplab/plugins/filter.md
new file mode 100644
index 00000000000..0853ea4d320
--- /dev/null
+++ b/doc/development/fe_guide/droplab/plugins/filter.md
@@ -0,0 +1,45 @@
+# Filter
+
+`Filter` is a plugin that allows for filtering data that has been added
+to the dropdown using a simple fuzzy string search of an input value.
+
+## Usage
+
+Add the `Filter` object to the plugins array of a `DropLab.prototype.init` or `DropLab.prototype.addHook` call.
+
+* `Filter` requires a config value for `template`.
+* `template` should be the key of the objects within your data array that you want to compare
+to the user input string, for filtering.
+
+```html
+<input href="#" id="trigger" data-dropdown-trigger="#list">
+<ul id="list" data-dropdown data-dynamic>
+ <li><a href="#" data-id="{{id}}">{{text}}</a></li>
+<ul>
+```
+```js
+ const droplab = new DropLab();
+
+ const trigger = document.getElementById('trigger');
+ const list = document.getElementById('list');
+
+ droplab.init(trigger, list, [Filter], {
+ Filter: {
+ template: 'text',
+ },
+ });
+
+ droplab.addData('trigger', [{
+ id: 0,
+ text: 'Jacob',
+ }, {
+ id: 1,
+ text: 'Jeff',
+ }]);
+```
+
+Above, the input string will be compared against the `test` key of the passed data objects.
+
+Optionally you can set `filterFunction` to a function. This function will be used instead
+of `Filter`'s built in string search. `filterFunction` is passed 2 arguments, the first
+is one of the data objects, the second is the current input value.
diff --git a/doc/development/fe_guide/droplab/plugins/input_setter.md b/doc/development/fe_guide/droplab/plugins/input_setter.md
new file mode 100644
index 00000000000..a549603c20d
--- /dev/null
+++ b/doc/development/fe_guide/droplab/plugins/input_setter.md
@@ -0,0 +1,60 @@
+# InputSetter
+
+`InputSetter` is a plugin that allows for udating DOM out of the scope of droplab when a list item is clicked.
+
+## Usage
+
+Add the `InputSetter` object to the plugins array of a `DropLab.prototype.init` or `DropLab.prototype.addHook` call.
+
+* `InputSetter` requires a config value for `input` and `valueAttribute`.
+* `input` should be the DOM element that you want to manipulate.
+* `valueAttribute` should be a string that is the name of an attribute on your list items that is used to get the value
+to update the `input` element with.
+
+You can also set the `InputSetter` config to an array of objects, which will allow you to update multiple elements.
+
+
+```html
+<input id="input" value="">
+<div id="div" data-selected-id=""></div>
+
+<input href="#" id="trigger" data-dropdown-trigger="#list">
+<ul id="list" data-dropdown data-dynamic>
+ <li><a href="#" data-id="{{id}}">{{text}}</a></li>
+<ul>
+```
+```js
+ const droplab = new DropLab();
+
+ const trigger = document.getElementById('trigger');
+ const list = document.getElementById('list');
+
+ const input = document.getElementById('input');
+ const div = document.getElementById('div');
+
+ droplab.init(trigger, list, [InputSetter], {
+ InputSetter: [{
+ input: input,
+ valueAttribute: 'data-id',
+ } {
+ input: div,
+ valueAttribute: 'data-id',
+ inputAttribute: 'data-selected-id',
+ }],
+ });
+
+ droplab.addData('trigger', [{
+ id: 0,
+ text: 'Jacob',
+ }, {
+ id: 1,
+ text: 'Jeff',
+ }]);
+```
+
+Above, if the second list item was clicked, it would update the `#input` element
+to have a `value` of `1`, it would also update the `#div` element's `data-selected-id` to `1`.
+
+Optionally you can set `inputAttribute` to a string that is the name of an attribute on your `input` element that you want to update.
+If you do not provide an `inputAttribute`, `InputSetter` will update the `value` of the `input` element if it is an `INPUT` element,
+or the `textContent` of the `input` element if it is not an `INPUT` element.
diff --git a/doc/development/fe_guide/img/boards_diagram.png b/doc/development/fe_guide/img/boards_diagram.png
new file mode 100644
index 00000000000..7a2cf972fd0
--- /dev/null
+++ b/doc/development/fe_guide/img/boards_diagram.png
Binary files differ
diff --git a/doc/development/fe_guide/img/testing_triangle.png b/doc/development/fe_guide/img/testing_triangle.png
new file mode 100644
index 00000000000..7a9a848c2ee
--- /dev/null
+++ b/doc/development/fe_guide/img/testing_triangle.png
Binary files differ
diff --git a/doc/development/fe_guide/img/vue_arch.png b/doc/development/fe_guide/img/vue_arch.png
new file mode 100644
index 00000000000..a67706c7c1e
--- /dev/null
+++ b/doc/development/fe_guide/img/vue_arch.png
Binary files differ
diff --git a/doc/development/fe_guide/index.md b/doc/development/fe_guide/index.md
new file mode 100644
index 00000000000..64bcb4a0257
--- /dev/null
+++ b/doc/development/fe_guide/index.md
@@ -0,0 +1,151 @@
+# Frontend Development Guidelines
+
+This document describes various guidelines to ensure consistency and quality
+across GitLab's frontend team.
+
+## Overview
+
+GitLab is built on top of [Ruby on Rails][rails] using [Haml][haml] with
+[Hamlit][hamlit]. Be wary of [the limitations that come with using
+Hamlit][hamlit-limits]. We also use [SCSS][scss] and plain JavaScript with
+modern ECMAScript standards supported through [Babel][babel] and ES module
+support through [webpack][webpack].
+
+We also utilize [webpack][webpack] to handle the bundling, minification, and
+compression of our assets.
+
+Working with our frontend assets requires Node (v4.3 or greater) and Yarn
+(v0.17 or greater). You can find information on how to install these on our
+[installation guide][install].
+
+[jQuery][jquery] is used throughout the application's JavaScript, with
+[Vue.js][vue] for particularly advanced, dynamic elements.
+
+### Browser Support
+
+For our currently-supported browsers, see our [requirements][requirements].
+
+---
+
+## Development Process
+
+When you are assigned an issue please follow the next steps:
+
+### Divide a big feature into small Merge Requests
+1. Big Merge Request are painful to review. In order to make this process easier we
+must break a big feature into smaller ones and create a Merge Request for each step.
+1. First step is to create a branch from `master`, let's call it `new-feature`. This branch
+will be the recipient of all the smaller Merge Requests. Only this one will be merged to master.
+1. Don't do any work on this one, let's keep it synced with master.
+1. Create a new branch from `new-feature`, let's call it `new-feature-step-1`. We advise you
+to clearly identify which step the branch represents.
+1. Do the first part of the modifications in this branch. The target branch of this Merge Request
+should be `new-feature`.
+1. Once `new-feature-step-1` gets merged into `new-feature` we can continue our work. Create a new
+branch from `new-feature`, let's call it `new-feature-step-2` and repeat the process done before.
+
+```shell
+master
+└─ new-feature
+ ├─ new-feature-step-1
+ ├─ new-feature-step-2
+ └─ new-feature-step-3
+```
+
+**Tips**
+- Make sure `new-feature` branch is always synced with `master`: merge master frequently.
+- Do the same for the feature branch you have opened. This can be accomplished by merging `master` into `new-feature` and `new-feature` into `new-feature-step-*`
+- Avoid rewriting history.
+
+### Share your work early
+1. Before writing code guarantee your vision of the architecture is aligned with
+GitLab's architecture.
+1. Add a diagram to the issue and ask a Frontend Architecture about it.
+
+ ![Diagram of Issue Boards Architecture](img/boards_diagram.png)
+
+1. Don't take more than one week between starting work on a feature and
+sharing a Merge Request with a reviewer or a maintainer.
+
+### Vue features
+1. Follow the steps in [Vue.js Best Practices](vue.md)
+1. Follow the style guide.
+1. Only a handful of people are allowed to merge Vue related features.
+Reach out to one of Vue experts early in this process.
+
+
+---
+
+## [Architecture](architecture.md)
+How we go about making fundamental design decisions in GitLab's frontend team
+or make changes to our frontend development guidelines.
+
+---
+
+## [Testing](testing.md)
+How we write frontend tests, run the GitLab test suite, and debug test related
+issues.
+
+---
+
+## [Design Patterns](design_patterns.md)
+Common JavaScript design patterns in GitLab's codebase.
+
+---
+
+## [Vue.js Best Practices](vue.md)
+Vue specific design patterns and practices.
+
+---
+
+## Style Guides
+
+### [JavaScript Style Guide](style_guide_js.md)
+
+We use eslint to enforce our JavaScript style guides. Our guide is based on
+the excellent [Airbnb][airbnb-js-style-guide] style guide with a few small
+changes.
+
+### [SCSS Style Guide](style_guide_scss.md)
+
+Our SCSS conventions which are enforced through [scss-lint][scss-lint].
+
+---
+
+## [Performance](performance.md)
+Best practices for monitoring and maximizing frontend performance.
+
+---
+
+## [Security](security.md)
+Frontend security practices.
+
+---
+
+## [Accessibility](accessibility.md)
+Our accessibility standards and resources.
+
+
+[rails]: http://rubyonrails.org/
+[haml]: http://haml.info/
+[hamlit]: https://github.com/k0kubun/hamlit
+[hamlit-limits]: https://github.com/k0kubun/hamlit/blob/master/REFERENCE.md#limitations
+[scss]: http://sass-lang.com/
+[babel]: https://babeljs.io/
+[webpack]: https://webpack.js.org/
+[jquery]: https://jquery.com/
+[vue]: http://vuejs.org/
+[airbnb-js-style-guide]: https://github.com/airbnb/javascript
+[scss-lint]: https://github.com/brigade/scss-lint
+[install]: ../../install/installation.md#4-node
+[requirements]: ../../install/requirements.md#supported-web-browsers
+
+---
+
+## [DropLab](droplab/droplab.md)
+Our internal `DropLab` dropdown library.
+
+* [DropLab](droplab/droplab.md)
+* [Ajax plugin](droplab/plugins/ajax.md)
+* [Filter plugin](droplab/plugins/filter.md)
+* [InputSetter plugin](droplab/plugins/input_setter.md)
diff --git a/doc/development/fe_guide/performance.md b/doc/development/fe_guide/performance.md
new file mode 100644
index 00000000000..2ddcbe13afa
--- /dev/null
+++ b/doc/development/fe_guide/performance.md
@@ -0,0 +1,94 @@
+# Performance
+
+## Best Practices
+
+### Realtime Components
+
+When writing code for realtime features we have to keep a couple of things in mind:
+1. Do not overload the server with requests.
+1. It should feel realtime.
+
+Thus, we must strike a balance between sending requests and the feeling of realtime.
+Use the following rules when creating realtime solutions.
+
+1. The server will tell you how much to poll by sending `Poll-Interval` in the header.
+Use that as your polling interval. This way it is [easy for system administrators to change the
+polling rate](../../administration/polling.md).
+A `Poll-Interval: -1` means you should disable polling, and this must be implemented.
+1. A response with HTTP status `4XX` or `5XX` should disable polling as well.
+1. Use a common library for polling.
+1. Poll on active tabs only. Please use [Visibility](https://github.com/ai/visibilityjs).
+1. Use regular polling intervals, do not use backoff polling, or jitter, as the interval will be
+controlled by the server.
+1. The backend code will most likely be using etags. You do not and should not check for status
+`304 Not Modified`. The browser will transform it for you.
+
+## Reducing Asset Footprint
+
+### Page-specific JavaScript
+
+Certain pages may require the use of a third party library, such as [d3][d3] for
+the User Activity Calendar and [Chart.js][chartjs] for the Graphs pages. These
+libraries increase the page size significantly, and impact load times due to
+bandwidth bottlenecks and the browser needing to parse more JavaScript.
+
+In cases where libraries are only used on a few specific pages, we use
+"page-specific JavaScript" to prevent the main `main.js` file from
+becoming unnecessarily large.
+
+Steps to split page-specific JavaScript from the main `main.js`:
+
+1. Create a directory for the specific page(s), e.g. `graphs/`.
+1. In that directory, create a `namespace_bundle.js` file, e.g. `graphs_bundle.js`.
+1. Add the new "bundle" file to the list of entry files in `config/webpack.config.js`.
+ - For example: `graphs: './graphs/graphs_bundle.js',`.
+1. Move code reliant on these libraries into the `graphs` directory.
+1. In `graphs_bundle.js` add CommonJS `require('./path_to_some_component.js');` statements to load any other files in this directory. Make sure to use relative urls.
+1. In the relevant views, add the scripts to the page with the following:
+
+```haml
+- content_for :page_specific_javascripts do
+ = webpack_bundle_tag 'lib_chart'
+ = webpack_bundle_tag 'graphs'
+```
+
+The above loads `chart.js` and `graphs_bundle.js` for this page only. `chart.js`
+is separated from the bundle file so it can be cached separately from the bundle
+and reused for other pages that also rely on the library. For an example, see
+[this Haml file][page-specific-js-example].
+
+### Code Splitting
+
+> *TODO* flesh out this section once webpack is ready for code-splitting
+
+### Minimizing page size
+
+A smaller page size means the page loads faster (especially important on mobile
+and poor connections), the page is parsed more quickly by the browser, and less
+data is used for users with capped data plans.
+
+General tips:
+
+- Don't add new fonts.
+- Prefer font formats with better compression, e.g. WOFF2 is better than WOFF, which is better than TTF.
+- Compress and minify assets wherever possible (For CSS/JS, Sprockets and webpack do this for us).
+- If some functionality can reasonably be achieved without adding extra libraries, avoid them.
+- Use page-specific JavaScript as described above to dynamically load libraries that are only needed on certain pages.
+
+-------
+
+## Additional Resources
+
+- [WebPage Test][web-page-test] for testing site loading time and size.
+- [Google PageSpeed Insights][pagespeed-insights] grades web pages and provides feedback to improve the page.
+- [Profiling with Chrome DevTools][google-devtools-profiling]
+- [Browser Diet][browser-diet] is a community-built guide that catalogues practical tips for improving web page performance.
+
+
+[web-page-test]: http://www.webpagetest.org/
+[pagespeed-insights]: https://developers.google.com/speed/pagespeed/insights/
+[google-devtools-profiling]: https://developers.google.com/web/tools/chrome-devtools/profile/?hl=en
+[browser-diet]: https://browserdiet.com/
+[d3]: https://d3js.org/
+[chartjs]: http://www.chartjs.org/
+[page-specific-js-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/13bb9ed77f405c5f6ee4fdbc964ecf635c9a223f/app/views/projects/graphs/_head.html.haml#L6-8
diff --git a/doc/development/fe_guide/security.md b/doc/development/fe_guide/security.md
new file mode 100644
index 00000000000..19e72c1d368
--- /dev/null
+++ b/doc/development/fe_guide/security.md
@@ -0,0 +1,92 @@
+# Security
+### Resources
+
+[Mozilla’s HTTP Observatory CLI][observatory-cli] and the
+[Qualys SSL Labs Server Test][qualys-ssl] are good resources for finding
+potential problems and ensuring compliance with security best practices.
+
+<!-- Uncomment these sections when CSP/SRI are implemented.
+### Content Security Policy (CSP)
+
+Content Security Policy is a web standard that intends to mitigate certain
+forms of Cross-Site Scripting (XSS) as well as data injection.
+
+Content Security Policy rules should be taken into consideration when
+implementing new features, especially those that may rely on connection with
+external services.
+
+GitLab's CSP is used for the following:
+
+- Blocking plugins like Flash and Silverlight from running at all on our pages.
+- Blocking the use of scripts and stylesheets downloaded from external sources.
+- Upgrading `http` requests to `https` when possible.
+- Preventing `iframe` elements from loading in most contexts.
+
+Some exceptions include:
+
+- Scripts from Google Analytics and Piwik if either is enabled.
+- Connecting with GitHub, Bitbucket, GitLab.com, etc. to allow project importing.
+- Connecting with Google, Twitter, GitHub, etc. to allow OAuth authentication.
+
+We use [the Secure Headers gem][secure_headers] to enable Content
+Security Policy headers in the GitLab Rails app.
+
+Some resources on implementing Content Security Policy:
+
+- [MDN Article on CSP][mdn-csp]
+- [GitHub’s CSP Journey on the GitHub Engineering Blog][github-eng-csp]
+- The Dropbox Engineering Blog's series on CSP: [1][dropbox-csp-1], [2][dropbox-csp-2], [3][dropbox-csp-3], [4][dropbox-csp-4]
+
+### Subresource Integrity (SRI)
+
+Subresource Integrity prevents malicious assets from being provided by a CDN by
+guaranteeing that the asset downloaded is identical to the asset the server
+is expecting.
+
+The Rails app generates a unique hash of the asset, which is used as the
+asset's `integrity` attribute. The browser generates the hash of the asset
+on-load and will reject the asset if the hashes do not match.
+
+All CSS and JavaScript assets should use Subresource Integrity.
+
+Some resources on implementing Subresource Integrity:
+
+- [MDN Article on SRI][mdn-sri]
+- [Subresource Integrity on the GitHub Engineering Blog][github-eng-sri]
+
+-->
+
+### Including external resources
+
+External fonts, CSS, and JavaScript should never be used with the exception of
+Google Analytics and Piwik - and only when the instance has enabled it. Assets
+should always be hosted and served locally from the GitLab instance. Embedded
+resources via `iframes` should never be used except in certain circumstances
+such as with ReCaptcha, which cannot be used without an `iframe`.
+
+### Avoiding inline scripts and styles
+
+In order to protect users from [XSS vulnerabilities][xss], we will disable
+inline scripts in the future using Content Security Policy.
+
+While inline scripts can be useful, they're also a security concern. If
+user-supplied content is unintentionally left un-sanitized, malicious users can
+inject scripts into the web app.
+
+Inline styles should be avoided in almost all cases, they should only be used
+when no alternatives can be found. This allows reusability of styles as well as
+readability.
+
+
+[observatory-cli]: https://github.com/mozilla/http-observatory-cli
+[qualys-ssl]: https://www.ssllabs.com/ssltest/analyze.html
+[secure_headers]: https://github.com/twitter/secureheaders
+[mdn-csp]: https://developer.mozilla.org/en-US/docs/Web/Security/CSP
+[github-eng-csp]: http://githubengineering.com/githubs-csp-journey/
+[dropbox-csp-1]: https://blogs.dropbox.com/tech/2015/09/on-csp-reporting-and-filtering/
+[dropbox-csp-2]: https://blogs.dropbox.com/tech/2015/09/unsafe-inline-and-nonce-deployment/
+[dropbox-csp-3]: https://blogs.dropbox.com/tech/2015/09/csp-the-unexpected-eval/
+[dropbox-csp-4]: https://blogs.dropbox.com/tech/2015/09/csp-third-party-integrations-and-privilege-separation/
+[mdn-sri]: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
+[github-eng-sri]: http://githubengineering.com/subresource-integrity/
+[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
diff --git a/doc/development/fe_guide/style_guide_js.md b/doc/development/fe_guide/style_guide_js.md
new file mode 100644
index 00000000000..ae844fa1051
--- /dev/null
+++ b/doc/development/fe_guide/style_guide_js.md
@@ -0,0 +1,503 @@
+# Style guides and linting
+See the relevant style guides for our guidelines and for information on linting:
+
+## JavaScript
+We defer to [Airbnb][airbnb-js-style-guide] on most style-related
+conventions and enforce them with eslint.
+
+See [our current .eslintrc][eslintrc] for specific rules and patterns.
+
+### Common
+
+#### ESlint
+
+1. **Never** disable eslint rules unless you have a good reason.
+You may see a lot of legacy files with `/* eslint-disable some-rule, some-other-rule */`
+at the top, but legacy files are a special case. Any time you develop a new feature or
+refactor an existing one, you should abide by the eslint rules.
+
+1. **Never Ever EVER** disable eslint globally for a file
+ ```javascript
+ // bad
+ /* eslint-disable */
+
+ // better
+ /* eslint-disable some-rule, some-other-rule */
+
+ // best
+ // nothing :)
+ ```
+
+1. If you do need to disable a rule for a single violation, try to do it as locally as possible
+ ```javascript
+ // bad
+ /* eslint-disable no-new */
+
+ import Foo from 'foo';
+
+ new Foo();
+
+ // better
+ import Foo from 'foo';
+
+ // eslint-disable-next-line no-new
+ new Foo();
+ ```
+1. There are few rules that we need to disable due to technical debt. Which are:
+ 1. [no-new][eslint-new]
+ 1. [class-methods-use-this][eslint-this]
+
+1. When they are needed _always_ place ESlint directive comment blocks on the first line of a script,
+followed by any global declarations, then a blank newline prior to any imports or code.
+ ```javascript
+ // bad
+ /* global Foo */
+ /* eslint-disable no-new */
+ import Bar from './bar';
+
+ // good
+ /* eslint-disable no-new */
+ /* global Foo */
+
+ import Bar from './bar';
+ ```
+
+1. **Never** disable the `no-undef` rule. Declare globals with `/* global Foo */` instead.
+
+1. When declaring multiple globals, always use one `/* global [name] */` line per variable.
+ ```javascript
+ // bad
+ /* globals Flash, Cookies, jQuery */
+
+ // good
+ /* global Flash */
+ /* global Cookies */
+ /* global jQuery */
+ ```
+
+1. Use up to 3 parameters for a function or class. If you need more accept an Object instead.
+ ```javascript
+ // bad
+ fn(p1, p2, p3, p4) {}
+
+ // good
+ fn(options) {}
+ ```
+
+#### Modules, Imports, and Exports
+1. Use ES module syntax to import modules
+ ```javascript
+ // bad
+ require('foo');
+
+ // good
+ import Foo from 'foo';
+
+ // bad
+ module.exports = Foo;
+
+ // good
+ export default Foo;
+ ```
+
+1. Relative paths: Unless you are writing a test, always reference other scripts using
+relative paths instead of `~`
+ * In **app/assets/javascripts**:
+
+ ```javascript
+ // bad
+ import Foo from '~/foo'
+
+ // good
+ import Foo from '../foo';
+ ```
+ * In **spec/javascripts**:
+
+ ```javascript
+ // bad
+ import Foo from '../../app/assets/javascripts/foo'
+
+ // good
+ import Foo from '~/foo';
+ ```
+
+1. Avoid using IIFE. Although we have a lot of examples of files which wrap their
+contents in IIFEs (immediately-invoked function expressions),
+this is no longer necessary after the transition from Sprockets to webpack.
+Do not use them anymore and feel free to remove them when refactoring legacy code.
+
+1. Avoid adding to the global namespace.
+ ```javascript
+ // bad
+ window.MyClass = class { /* ... */ };
+
+ // good
+ export default class MyClass { /* ... */ }
+ ```
+
+1. Side effects are forbidden in any script which contains exports
+ ```javascript
+ // bad
+ export default class MyClass { /* ... */ }
+
+ document.addEventListener("DOMContentLoaded", function(event) {
+ new MyClass();
+ }
+ ```
+
+
+#### Data Mutation and Pure functions
+1. Strive to write many small pure functions, and minimize where mutations occur.
+ ```javascript
+ // bad
+ const values = {foo: 1};
+
+ function impureFunction(items) {
+ const bar = 1;
+
+ items.foo = items.a * bar + 2;
+
+ return items.a;
+ }
+
+ const c = impureFunction(values);
+
+ // good
+ var values = {foo: 1};
+
+ function pureFunction (foo) {
+ var bar = 1;
+
+ foo = foo * bar + 2;
+
+ return foo;
+ }
+
+ var c = pureFunction(values.foo);
+ ```
+
+1. Avoid constructors with side-effects
+
+1. Prefer `.map`, `.reduce` or `.filter` over `.forEach`
+A forEach will cause side effects, it will be mutating the array being iterated. Prefer using `.map`,
+`.reduce` or `.filter`
+ ```javascript
+ const users = [ { name: 'Foo' }, { name: 'Bar' } ];
+
+ // bad
+ users.forEach((user, index) => {
+ user.id = index;
+ });
+
+ // good
+ const usersWithId = users.map((user, index) => {
+ return Object.assign({}, user, { id: index });
+ });
+ ```
+
+#### Parse Strings into Numbers
+1. `parseInt()` is preferable over `Number()` or `+`
+ ```javascript
+ // bad
+ +'10' // 10
+
+ // good
+ Number('10') // 10
+
+ // better
+ parseInt('10', 10);
+ ```
+
+#### CSS classes used for JavaScript
+1. If the class is being used in Javascript it needs to be prepend with `js-`
+ ```html
+ // bad
+ <button class="add-user">
+ Add User
+ </button>
+
+ // good
+ <button class="js-add-user">
+ Add User
+ </button>
+ ```
+
+### Vue.js
+
+#### Basic Rules
+1. The service has it's own file
+1. The store has it's own file
+1. Use a function in the bundle file to instantiate the Vue component:
+ ```javascript
+ // bad
+ class {
+ init() {
+ new Component({})
+ }
+ }
+
+ // good
+ document.addEventListener('DOMContentLoaded', () => new Vue({
+ el: '#element',
+ components: {
+ componentName
+ },
+ render: createElement => createElement('component-name'),
+ }));
+ ```
+
+1. Don not use a singleton for the service or the store
+ ```javascript
+ // bad
+ class Store {
+ constructor() {
+ if (!this.prototype.singleton) {
+ // do something
+ }
+ }
+ }
+
+ // good
+ class Store {
+ constructor() {
+ // do something
+ }
+ }
+ ```
+
+#### Naming
+1. **Extensions**: Use `.vue` extension for Vue components.
+1. **Reference Naming**: Use camelCase for their instances:
+ ```javascript
+ // good
+ import cardBoard from 'cardBoard'
+
+ components: {
+ cardBoard:
+ };
+ ```
+
+1. **Props Naming:** Avoid using DOM component prop names.
+1. **Props Naming:** Use kebab-case instead of camelCase to provide props in templates.
+ ```javascript
+ // bad
+ <component class="btn">
+
+ // good
+ <component css-class="btn">
+
+ // bad
+ <component myProp="prop" />
+
+ // good
+ <component my-prop="prop" />
+ ```
+
+#### Alignment
+1. Follow these alignment styles for the template method:
+ ```javascript
+ // bad
+ <component v-if="bar"
+ param="baz" />
+
+ <button class="btn">Click me</button>
+
+ // good
+ <component
+ v-if="bar"
+ param="baz"
+ />
+
+ <button class="btn">
+ Click me
+ </button>
+
+ // if props fit in one line then keep it on the same line
+ <component bar="bar" />
+ ```
+
+#### Quotes
+1. Always use double quotes `"` inside templates and single quotes `'` for all other JS.
+ ```javascript
+ // bad
+ template: `
+ <button :class='style'>Button</button>
+ `
+
+ // good
+ template: `
+ <button :class="style">Button</button>
+ `
+ ```
+
+#### Props
+1. Props should be declared as an object
+ ```javascript
+ // bad
+ props: ['foo']
+
+ // good
+ props: {
+ foo: {
+ type: String,
+ required: false,
+ default: 'bar'
+ }
+ }
+ ```
+
+1. Required key should always be provided when declaring a prop
+ ```javascript
+ // bad
+ props: {
+ foo: {
+ type: String,
+ }
+ }
+
+ // good
+ props: {
+ foo: {
+ type: String,
+ required: false,
+ default: 'bar'
+ }
+ }
+ ```
+
+1. Default key should always be provided if the prop is not required:
+ ```javascript
+ // bad
+ props: {
+ foo: {
+ type: String,
+ required: false,
+ }
+ }
+
+ // good
+ props: {
+ foo: {
+ type: String,
+ required: false,
+ default: 'bar'
+ }
+ }
+
+ // good
+ props: {
+ foo: {
+ type: String,
+ required: true
+ }
+ }
+ ```
+
+#### Data
+1. `data` method should always be a function
+
+ ```javascript
+ // bad
+ data: {
+ foo: 'foo'
+ }
+
+ // good
+ data() {
+ return {
+ foo: 'foo'
+ };
+ }
+ ```
+
+#### Directives
+
+1. Shorthand `@` is preferable over `v-on`
+ ```javascript
+ // bad
+ <component v-on:click="eventHandler"/>
+
+
+ // good
+ <component @click="eventHandler"/>
+ ```
+
+1. Shorthand `:` is preferable over `v-bind`
+ ```javascript
+ // bad
+ <component v-bind:class="btn"/>
+
+
+ // good
+ <component :class="btn"/>
+ ```
+
+#### Closing tags
+1. Prefer self closing component tags
+ ```javascript
+ // bad
+ <component></component>
+
+ // good
+ <component />
+ ```
+
+#### Ordering
+1. Order for a Vue Component:
+ 1. `name`
+ 1. `props`
+ 1. `mixins`
+ 1. `data`
+ 1. `components`
+ 1. `computedProps`
+ 1. `methods`
+ 1. `beforeCreate`
+ 1. `created`
+ 1. `beforeMount`
+ 1. `mounted`
+ 1. `beforeUpdate`
+ 1. `updated`
+ 1. `activated`
+ 1. `deactivated`
+ 1. `beforeDestroy`
+ 1. `destroyed`
+
+#### Vue and Boostrap
+1. Tooltips: Do not rely on `has-tooltip` class name for Vue components
+ ```javascript
+ // bad
+ <span
+ class="has-tooltip"
+ title="Some tooltip text">
+ Text
+ </span>
+
+ // good
+ <span
+ v-tooltip
+ title="Some tooltip text">
+ Text
+ </span>
+ ```
+
+1. Tooltips: When using a tooltip, include the tooltip directive, `./app/assets/javascripts/vue_shared/directives/tooltip.js`
+
+1. Don't change `data-original-title`.
+ ```javascript
+ // bad
+ <span data-original-title="tooltip text">Foo</span>
+
+ // good
+ <span title="tooltip text">Foo</span>
+
+ $('span').tooltip('fixTitle');
+ ```
+
+
+## SCSS
+- [SCSS](style_guide_scss.md)
+
+[airbnb-js-style-guide]: https://github.com/airbnb/javascript
+[eslintrc]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.eslintrc
+[eslint-this]: http://eslint.org/docs/rules/class-methods-use-this
+[eslint-new]: http://eslint.org/docs/rules/no-new
diff --git a/doc/development/scss_styleguide.md b/doc/development/fe_guide/style_guide_scss.md
index a79f4073cde..77b308c4a43 100644
--- a/doc/development/scss_styleguide.md
+++ b/doc/development/fe_guide/style_guide_scss.md
@@ -35,7 +35,7 @@ between the property and its value.
```scss
// Bad
-.container-item {
+.container-item {
width: 100px; height: 100px;
margin-top: 0;
}
@@ -63,7 +63,7 @@ between the property and its value.
}
```
-Note that there is an exception for single-line rulesets, although these are
+Note that there is an exception for single-line rulesets, although these are
not typically recommended.
```scss
@@ -72,7 +72,7 @@ p { margin: 0; padding: 0; }
### Colors
-HEX (hexadecimal) colors should use shorthand where possible, and should use
+HEX (hexadecimal) colors should use shorthand where possible, and should use
lower case letters to differentiate between letters and numbers, e.g. `#E3E3E3`
vs. `#e3e3e3`.
@@ -111,7 +111,7 @@ p {
### Semicolons
-Always include semicolons after every property. When the stylesheets are
+Always include semicolons after every property. When the stylesheets are
minified, the semicolons will be removed automatically.
```scss
@@ -144,7 +144,7 @@ padding: 10px;
### Zero Units
-Omit length units on zero values, they're unnecessary and not including them
+Omit length units on zero values, they're unnecessary and not including them
is slightly more performant.
```scss
@@ -161,36 +161,56 @@ is slightly more performant.
### Selectors with a `js-` Prefix
-Do not use any selector prefixed with `js-` for styling purposes. These
-selectors are intended for use only with JavaScript to allow for removal or
+Do not use any selector prefixed with `js-` for styling purposes. These
+selectors are intended for use only with JavaScript to allow for removal or
renaming without breaking styling.
+### IDs
+Don't use ID selectors in CSS.
+
+```scss
+// Bad
+#my-element {
+ padding: 0;
+}
+
+// Good
+.my-element {
+ padding: 0;
+}
+```
+
+### Variables
+Before adding a new variable for a color or a size, guarantee:
+1. There isn't already one
+2. There isn't a similar one we can use instead.
+
## Linting
-We use [SCSS Lint][scss-lint] to check for style guide conformity. It uses the
-ruleset in `.scss-lint.yml`, which is located in the home directory of the
+We use [SCSS Lint][scss-lint] to check for style guide conformity. It uses the
+ruleset in `.scss-lint.yml`, which is located in the home directory of the
project.
-To check if any warnings will be produced by your changes, you can run `rake
-scss_lint` in the GitLab directory. SCSS Lint will also run in GitLab CI to
+To check if any warnings will be produced by your changes, you can run `rake
+scss_lint` in the GitLab directory. SCSS Lint will also run in GitLab CI to
catch any warnings.
-If the Rake task is throwing warnings you don't understand, SCSS Lint's
+If the Rake task is throwing warnings you don't understand, SCSS Lint's
documentation includes [a full list of their linters][scss-lint-documentation].
### Fixing issues
-If you want to automate changing a large portion of the codebase to conform to
+If you want to automate changing a large portion of the codebase to conform to
the SCSS style guide, you can use [CSSComb][csscomb]. First install
-[Node][node] and [NPM][npm], then run `npm install csscomb -g` to install
-CSSComb globally (system-wide). Run it in the GitLab directory with
+[Node][node] and [NPM][npm], then run `npm install csscomb -g` to install
+CSSComb globally (system-wide). Run it in the GitLab directory with
`csscomb app/assets/stylesheets` to automatically fix issues with CSS/SCSS.
Note that this won't fix every problem, but it should fix a majority.
### Ignoring issues
-If you want a line or set of lines to be ignored by the linter, you can use
+If you want a line or set of lines to be ignored by the linter, you can use
`// scss-lint:disable RuleName` ([more info][disabling-linters]):
```scss
@@ -203,8 +223,8 @@ If you want a line or set of lines to be ignored by the linter, you can use
```
Make sure a comment is added on the line above the `disable` rule, otherwise the
-linter will throw a warning. `DisableLinterReason` is enabled to make sure the
-style guide isn't being ignored, and to communicate to others why the style
+linter will throw a warning. `DisableLinterReason` is enabled to make sure the
+style guide isn't being ignored, and to communicate to others why the style
guide is ignored in this instance.
[csscomb]: https://github.com/csscomb/csscomb.js
diff --git a/doc/development/fe_guide/testing.md b/doc/development/fe_guide/testing.md
new file mode 100644
index 00000000000..867c83f1e72
--- /dev/null
+++ b/doc/development/fe_guide/testing.md
@@ -0,0 +1,254 @@
+# Frontend Testing
+
+There are two types of test suites you'll encounter while developing frontend code
+at GitLab. We use Karma and Jasmine for JavaScript unit and integration testing, and RSpec
+feature tests with Capybara for e2e (end-to-end) integration testing.
+
+Unit and feature tests need to be written for all new features.
+Most of the time, you should use rspec for your feature tests.
+There are cases where the behaviour you are testing is not worth the time spent running the full application,
+for example, if you are testing styling, animation, edge cases or small actions that don't involve the backend,
+you should write an integration test using Jasmine.
+
+![Testing priority triangle](img/testing_triangle.png)
+
+_This diagram demonstrates the relative priority of each test type we use_
+
+Regression tests should be written for bug fixes to prevent them from recurring in the future.
+
+See [the Testing Standards and Style Guidelines](../testing.md)
+for more information on general testing practices at GitLab.
+
+## Karma test suite
+
+GitLab uses the [Karma][karma] test runner with [Jasmine][jasmine] as its test
+framework for our JavaScript unit and integration tests. For integration tests,
+we generate HTML files using RSpec (see `spec/javascripts/fixtures/*.rb` for examples).
+Some fixtures are still HAML templates that are translated to HTML files using the same mechanism (see `static_fixtures.rb`).
+Adding these static fixtures should be avoided as they are harder to keep up to date with real views.
+The existing static fixtures will be migrated over time.
+Please see [gitlab-org/gitlab-ce#24753](https://gitlab.com/gitlab-org/gitlab-ce/issues/24753) to track our progress.
+Fixtures are served during testing by the [jasmine-jquery][jasmine-jquery] plugin.
+
+JavaScript tests live in `spec/javascripts/`, matching the folder structure
+of `app/assets/javascripts/`: `app/assets/javascripts/behaviors/autosize.js`
+has a corresponding `spec/javascripts/behaviors/autosize_spec.js` file.
+
+Keep in mind that in a CI environment, these tests are run in a headless
+browser and you will not have access to certain APIs, such as
+[`Notification`](https://developer.mozilla.org/en-US/docs/Web/API/notification),
+which will have to be stubbed.
+
+### Best practice
+
+#### Naming unit tests
+
+When writing describe test blocks to test specific functions/methods,
+please use the method name as the describe block name.
+
+```javascript
+// Good
+describe('methodName', () => {
+ it('passes', () => {
+ expect(true).toEqual(true);
+ });
+});
+
+// Bad
+describe('#methodName', () => {
+ it('passes', () => {
+ expect(true).toEqual(true);
+ });
+});
+
+// Bad
+describe('.methodName', () => {
+ it('passes', () => {
+ expect(true).toEqual(true);
+ });
+});
+```
+#### Testing Promises
+
+When testing Promises you should always make sure that the test is asynchronous and rejections are handled.
+Your Promise chain should therefore end with a call of the `done` callback and `done.fail` in case an error occurred.
+
+```javascript
+// Good
+it('tests a promise', (done) => {
+ promise
+ .then((data) => {
+ expect(data).toBe(asExpected);
+ })
+ .then(done)
+ .catch(done.fail);
+});
+
+// Good
+it('tests a promise rejection', (done) => {
+ promise
+ .then(done.fail)
+ .catch((error) => {
+ expect(error).toBe(expectedError);
+ })
+ .then(done)
+ .catch(done.fail);
+});
+
+// Bad (missing done callback)
+it('tests a promise', () => {
+ promise
+ .then((data) => {
+ expect(data).toBe(asExpected);
+ })
+});
+
+// Bad (missing catch)
+it('tests a promise', (done) => {
+ promise
+ .then((data) => {
+ expect(data).toBe(asExpected);
+ })
+ .then(done)
+});
+
+// Bad (use done.fail in asynchronous tests)
+it('tests a promise', (done) => {
+ promise
+ .then((data) => {
+ expect(data).toBe(asExpected);
+ })
+ .then(done)
+ .catch(fail)
+});
+
+// Bad (missing catch)
+it('tests a promise rejection', (done) => {
+ promise
+ .catch((error) => {
+ expect(error).toBe(expectedError);
+ })
+ .then(done)
+});
+```
+
+#### Stubbing
+
+For unit tests, you should stub methods that are unrelated to the current unit you are testing.
+If you need to use a prototype method, instantiate an instance of the class and call it there instead of mocking the instance completely.
+
+For integration tests, you should stub methods that will effect the stability of the test if they
+execute their original behaviour. i.e. Network requests.
+
+### Vue.js unit tests
+See this [section][vue-test].
+
+### Running frontend tests
+
+`rake karma` runs the frontend-only (JavaScript) tests.
+It consists of two subtasks:
+
+- `rake karma:fixtures` (re-)generates fixtures
+- `rake karma:tests` actually executes the tests
+
+As long as the fixtures don't change, `rake karma:tests` (or `yarn karma`)
+is sufficient (and saves you some time).
+
+### Live testing and focused testing
+
+While developing locally, it may be helpful to keep karma running so that you
+can get instant feedback on as you write tests and modify code. To do this
+you can start karma with `npm run karma-start`. It will compile the javascript
+assets and run a server at `http://localhost:9876/` where it will automatically
+run the tests on any browser which connects to it. You can enter that url on
+multiple browsers at once to have it run the tests on each in parallel.
+
+While karma is running, any changes you make will instantly trigger a recompile
+and retest of the entire test suite, so you can see instantly if you've broken
+a test with your changes. You can use [jasmine focused][jasmine-focus] or
+excluded tests (with `fdescribe` or `xdescribe`) to get karma to run only the
+tests you want while you're working on a specific feature, but make sure to
+remove these directives when you commit your code.
+
+## RSpec Feature Integration Tests
+
+Information on setting up and running RSpec integration tests with
+[Capybara][capybara] can be found in the
+[general testing guide](../testing.md).
+
+## Gotchas
+
+### Errors due to use of unsupported JavaScript features
+
+Similar errors will be thrown if you're using JavaScript features not yet
+supported by the PhantomJS test runner which is used for both Karma and RSpec
+tests. We polyfill some JavaScript objects for older browsers, but some
+features are still unavailable:
+
+- Array.from
+- Array.first
+- Async functions
+- Generators
+- Array destructuring
+- For..Of
+- Symbol/Symbol.iterator
+- Spread
+
+Until these are polyfilled appropriately, they should not be used. Please
+update this list with additional unsupported features.
+
+### RSpec errors due to JavaScript
+
+By default RSpec unit tests will not run JavaScript in the headless browser
+and will simply rely on inspecting the HTML generated by rails.
+
+If an integration test depends on JavaScript to run correctly, you need to make
+sure the spec is configured to enable JavaScript when the tests are run. If you
+don't do this you'll see vague error messages from the spec runner.
+
+To enable a JavaScript driver in an `rspec` test, add `:js` to the
+individual spec or the context block containing multiple specs that need
+JavaScript enabled:
+
+```ruby
+# For one spec
+it 'presents information about abuse report', :js do
+ # assertions...
+end
+
+describe "Admin::AbuseReports", :js do
+ it 'presents information about abuse report' do
+ # assertions...
+ end
+ it 'shows buttons for adding to abuse report' do
+ # assertions...
+ end
+end
+```
+
+### Spinach errors due to missing JavaScript
+
+> **Note:** Since we are discouraging the use of Spinach when writing new
+> feature tests, you shouldn't ever need to use this. This information is kept
+> available for legacy purposes only.
+
+In Spinach, the JavaScript driver is enabled differently. In the `*.feature`
+file for the failing spec, add the `@javascript` flag above the Scenario:
+
+```
+@javascript
+Scenario: Developer can approve merge request
+ Given I am a "Shop" developer
+ And I visit project "Shop" merge requests page
+ And merge request 'Bug NS-04' must be approved
+ And I click link "Bug NS-04"
+ When I click link "Approve"
+ Then I should see approved merge request "Bug NS-04"
+```
+
+[capybara]: http://teamcapybara.github.io/capybara/
+[jasmine]: https://jasmine.github.io/
+[jasmine-focus]: https://jasmine.github.io/2.5/focused_specs.html
+[jasmine-jquery]: https://github.com/velesin/jasmine-jquery
+[karma]: http://karma-runner.github.io/
+[vue-test]:https://docs.gitlab.com/ce/development/fe_guide/vue.html#testing-vue-components
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
new file mode 100644
index 00000000000..a984bb6c94c
--- /dev/null
+++ b/doc/development/fe_guide/vue.md
@@ -0,0 +1,448 @@
+# Vue
+
+For more complex frontend features, we recommend using Vue.js. It shares
+some ideas with React.js as well as Angular.
+
+To get started with Vue, read through [their documentation][vue-docs].
+
+## When to use Vue.js
+
+We recommend using Vue for more complex features. Here are some guidelines for when to use Vue.js:
+
+- If you are starting a new feature or refactoring an old one that highly interacts with the DOM;
+- For real time data updates;
+- If you are creating a component that will be reused elsewhere;
+
+## When not to use Vue.js
+
+We don't want to refactor all GitLab frontend code into Vue.js, here are some guidelines for
+when not to use Vue.js:
+
+- Adding or changing static information;
+- Features that highly depend on jQuery will be hard to work with Vue.js;
+- Features without reactive data;
+
+As always, the Frontend Architectural Experts are available to help with any Vue or JavaScript questions.
+
+## Vue architecture
+
+All new features built with Vue.js must follow a [Flux architecture][flux].
+The main goal we are trying to achieve is to have only one data flow and only one data entry.
+In order to achieve this goal, each Vue bundle needs a Store - where we keep all the data -,
+a Service - that we use to communicate with the server - and a main Vue component.
+
+Think of the Main Vue Component as the entry point of your application. This is the only smart
+component that should exist in each Vue feature.
+This component is responsible for:
+1. Calling the Service to get data from the server
+1. Calling the Store to store the data received
+1. Mounting all the other components
+
+ ![Vue Architecture](img/vue_arch.png)
+
+You can also read about this architecture in vue docs about [state management][state-management]
+and about [one way data flow][one-way-data-flow].
+
+### Components, Stores and Services
+
+In some features implemented with Vue.js, like the [issue board][issue-boards]
+or [environments table][environments-table]
+you can find a clear separation of concerns:
+
+```
+new_feature
+├── components
+│ └── component.js.es6
+│ └── ...
+├── store
+│ └── new_feature_store.js.es6
+├── service
+│ └── new_feature_service.js.es6
+├── new_feature_bundle.js.es6
+```
+_For consistency purposes, we recommend you to follow the same structure._
+
+Let's look into each of them:
+
+### A `*_bundle.js` file
+
+This is the index file of your new feature. This is where the root Vue instance
+of the new feature should be.
+
+The Store and the Service should be imported and initialized in this file and
+provided as a prop to the main component.
+
+Don't forget to follow [these steps.][page_specific_javascript]
+
+### A folder for Components
+
+This folder holds all components that are specific of this new feature.
+If you need to use or create a component that will probably be used somewhere
+else, please refer to `vue_shared/components`.
+
+A good thumb rule to know when you should create a component is to think if
+it will be reusable elsewhere.
+
+For example, tables are used in a quite amount of places across GitLab, a table
+would be a good fit for a component. On the other hand, a table cell used only
+in one table would not be a good use of this pattern.
+
+You can read more about components in Vue.js site, [Component System][component-system]
+
+### A folder for the Store
+
+The Store is a class that allows us to manage the state in a single
+source of truth. It is not aware of the service or the components.
+
+The concept we are trying to follow is better explained by Vue documentation
+itself, please read this guide: [State Management][state-management]
+
+### A folder for the Service
+
+The Service is a class used only to communicate with the server.
+It does not store or manipulate any data. It is not aware of the store or the components.
+We use [vue-resource][vue-resource-repo] to communicate with the server.
+
+Vue Resource should only be imported in the service file.
+
+ ```javascript
+ import Vue from 'vue';
+ import VueResource from 'vue-resource';
+
+ Vue.use(VueResource);
+ ```
+
+### CSRF token
+We use a Vue Resource interceptor to manage the CSRF token.
+`app/assets/javascripts/vue_shared/vue_resource_interceptor.js` holds all our common interceptors.
+Note: You don't need to load `app/assets/javascripts/vue_shared/vue_resource_interceptor.js`
+since it's already being loaded by `common_vue.js`.
+
+### End Result
+
+The following example shows an application:
+
+```javascript
+// store.js
+export default class Store {
+
+ /**
+ * This is where we will iniatialize the state of our data.
+ * Usually in a small SPA you don't need any options when starting the store. In the case you do
+ * need guarantee it's an Object and it's documented.
+ *
+ * @param {Object} options
+ */
+ constructor(options) {
+ this.options = options;
+
+ // Create a state object to handle all our data in the same place
+ this.todos = []:
+ }
+
+ setTodos(todos = []) {
+ this.todos = todos;
+ }
+
+ addTodo(todo) {
+ this.todos.push(todo);
+ }
+
+ removeTodo(todoID) {
+ const state = this.todos;
+
+ const newState = state.filter((element) => {element.id !== todoID});
+
+ this.todos = newState;
+ }
+}
+
+// service.js
+import Vue from 'vue';
+import VueResource from 'vue-resource';
+import 'vue_shared/vue_resource_interceptor';
+
+Vue.use(VueResource);
+
+export default class Service {
+ constructor(options) {
+ this.todos = Vue.resource(endpoint.todosEndpoint);
+ }
+
+ getTodos() {
+ return this.todos.get();
+ }
+
+ addTodo(todo) {
+ return this.todos.put(todo);
+ }
+}
+// todo_component.vue
+<script>
+export default {
+ props: {
+ data: {
+ type: Object,
+ required: true,
+ },
+ }
+}
+</script>
+<template>
+ <div>
+ <h1>
+ Title: {{data.title}}
+ </h1>
+ <p>
+ {{data.text}}
+ </p>
+ </div>
+</template>
+
+// todos_main_component.vue
+<script>
+import Store from 'store';
+import Service from 'service';
+import TodoComponent from 'todoComponent';
+export default {
+ /**
+ * Although most data belongs in the store, each component it's own state.
+ * We want to show a loading spinner while we are fetching the todos, this state belong
+ * in the component.
+ *
+ * We need to access the store methods through all methods of our component.
+ * We need to access the state of our store.
+ */
+ data() {
+ const store = new Store();
+
+ return {
+ isLoading: false,
+ store: store,
+ todos: store.todos,
+ };
+ },
+
+ components: {
+ todo: TodoComponent,
+ },
+
+ created() {
+ this.service = new Service('todos');
+
+ this.getTodos();
+ },
+
+ methods: {
+ getTodos() {
+ this.isLoading = true;
+
+ this.service.getTodos()
+ .then(response => response.json())
+ .then((response) => {
+ this.store.setTodos(response);
+ this.isLoading = false;
+ })
+ .catch(() => {
+ this.isLoading = false;
+ // Show an error
+ });
+ },
+
+ addTodo(todo) {
+ this.service.addTodo(todo)
+ then(response => response.json())
+ .then((response) => {
+ this.store.addTodo(response);
+ })
+ .catch(() => {
+ // Show an error
+ });
+ }
+ }
+}
+</script>
+<template>
+ <div class="container">
+ <div v-if="isLoading">
+ <i
+ class="fa fa-spin fa-spinner"
+ aria-hidden="true" />
+ </div>
+
+ <div
+ v-if="!isLoading"
+ class="js-todo-list">
+ <template v-for='todo in todos'>
+ <todo :data="todo" />
+ </template>
+
+ <button
+ @click="addTodo"
+ class="js-add-todo">
+ Add Todo
+ </button>
+ </div>
+ <div>
+</template>
+
+// bundle.js
+import todoComponent from 'todos_main_component.vue';
+
+new Vue({
+ el: '.js-todo-app',
+ components: {
+ todoComponent,
+ },
+ render: createElement => createElement('todo-component' {
+ props: {
+ someProp: [],
+ }
+ }),
+});
+
+```
+
+The [issue boards service][issue-boards-service]
+is a good example of this pattern.
+
+## Style guide
+
+Please refer to the Vue section of our [style guide](style_guide_js.md#vuejs)
+for best practices while writing your Vue components and templates.
+
+## Testing Vue Components
+
+Each Vue component has a unique output. This output is always present in the render function.
+
+Although we can test each method of a Vue component individually, our goal must be to test the output
+of the render/template function, which represents the state at all times.
+
+Make use of Vue Resource Interceptors to mock data returned by the service.
+
+Here's how we would test the Todo App above:
+
+```javascript
+import component from 'todos_main_component';
+
+describe('Todos App', () => {
+ it('should render the loading state while the request is being made', () => {
+ const Component = Vue.extend(component);
+
+ const vm = new Component().$mount();
+
+ expect(vm.$el.querySelector('i.fa-spin')).toBeDefined();
+ });
+
+ describe('with data', () => {
+ // Mock the service to return data
+ const interceptor = (request, next) => {
+ next(request.respondWith(JSON.stringify([{
+ title: 'This is a todo',
+ body: 'This is the text'
+ }]), {
+ status: 200,
+ }));
+ };
+
+ let vm;
+
+ beforeEach(() => {
+ Vue.http.interceptors.push(interceptor);
+
+ const Component = Vue.extend(component);
+
+ vm = new Component().$mount();
+ });
+
+ afterEach(() => {
+ Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
+ });
+
+
+ it('should render todos', (done) => {
+ setTimeout(() => {
+ expect(vm.$el.querySelectorAll('.js-todo-list div').length).toBe(1);
+ done();
+ }, 0);
+ });
+ });
+
+ describe('add todo', () => {
+ let vm;
+ beforeEach(() => {
+ const Component = Vue.extend(component);
+ vm = new Component().$mount();
+ });
+ it('should add a todos', (done) => {
+ setTimeout(() => {
+ vm.$el.querySelector('.js-add-todo').click();
+
+ // Add a new interceptor to mock the add Todo request
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelectorAll('.js-todo-list div').length).toBe(2);
+ });
+ }, 0);
+ });
+ });
+});
+```
+#### Test the component's output
+The main return value of a Vue component is the rendered output. In order to test the component we
+need to test the rendered output. [Vue][vue-test] guide's to unit test show us exactly that:
+
+
+### Stubbing API responses
+[Vue Resource Interceptors][vue-resource-interceptor] allow us to add a interceptor with
+the response we need:
+
+```javascript
+ // Mock the service to return data
+ const interceptor = (request, next) => {
+ next(request.respondWith(JSON.stringify([{
+ title: 'This is a todo',
+ body: 'This is the text'
+ }]), {
+ status: 200,
+ }));
+ };
+
+ beforeEach(() => {
+ Vue.http.interceptors.push(interceptor);
+ });
+
+ afterEach(() => {
+ Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
+ });
+
+ it('should do something', (done) => {
+ setTimeout(() => {
+ // Test received data
+ done();
+ }, 0);
+ });
+```
+
+1. Use `$.mount()` to mount the component
+```javascript
+ // bad
+ new Component({
+ el: document.createElement('div')
+ });
+
+ // good
+ new Component().$mount();
+```
+
+[vue-docs]: http://vuejs.org/guide/index.html
+[issue-boards]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/assets/javascripts/boards
+[environments-table]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/assets/javascripts/environments
+[page_specific_javascript]: https://docs.gitlab.com/ce/development/frontend.html#page-specific-javascript
+[component-system]: https://vuejs.org/v2/guide/#Composing-with-Components
+[state-management]: https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch
+[one-way-data-flow]: https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow
+[vue-resource-repo]: https://github.com/pagekit/vue-resource
+[vue-resource-interceptor]: https://github.com/pagekit/vue-resource/blob/develop/docs/http.md#interceptors
+[vue-test]: https://vuejs.org/v2/guide/unit-testing.html
+[issue-boards-service]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/boards/services/board_service.js.es6
+[flux]: https://facebook.github.io/flux
diff --git a/doc/development/feature_flags.md b/doc/development/feature_flags.md
new file mode 100644
index 00000000000..5c6316b9ac6
--- /dev/null
+++ b/doc/development/feature_flags.md
@@ -0,0 +1,7 @@
+# Manage feature flags
+
+Starting from GitLab 9.3 we support feature flags via
+[Flipper](https://github.com/jnunemaker/flipper/). You should use the `Feature`
+class (defined in `lib/feature.rb`) in your code to get, set and list feature
+flags. During runtime you can set the values for the gates via the
+[admin API](../api/features.md).
diff --git a/doc/development/foreign_keys.md b/doc/development/foreign_keys.md
new file mode 100644
index 00000000000..0ab0deb156f
--- /dev/null
+++ b/doc/development/foreign_keys.md
@@ -0,0 +1,63 @@
+# Foreign Keys & Associations
+
+When adding an association to a model you must also add a foreign key. For
+example, say you have the following model:
+
+```ruby
+class User < ActiveRecord::Base
+ has_many :posts
+end
+```
+
+Here you will need to add a foreign key on column `posts.user_id`. This ensures
+that data consistency is enforced on database level. Foreign keys also mean that
+the database can very quickly remove associated data (e.g. when removing a
+user), instead of Rails having to do this.
+
+## Adding Foreign Keys In Migrations
+
+Foreign keys can be added concurrently using `add_concurrent_foreign_key` as
+defined in `Gitlab::Database::MigrationHelpers`. See the [Migration Style
+Guide](migration_style_guide.md) for more information.
+
+Keep in mind that you can only safely add foreign keys to existing tables after
+you have removed any orphaned rows. The method `add_concurrent_foreign_key`
+does not take care of this so you'll need to do so manually.
+
+## Cascading Deletes
+
+Every foreign key must define an `ON DELETE` clause, and in 99% of the cases
+this should be set to `CASCADE`.
+
+## Indexes
+
+When adding a foreign key in PostgreSQL the column is not indexed automatically,
+thus you must also add a concurrent index. Not doing so will result in cascading
+deletes being very slow.
+
+## Dependent Removals
+
+Don't define options such as `dependent: :destroy` or `dependent: :delete` when
+defining an association. Defining these options means Rails will handle the
+removal of data, instead of letting the database handle this in the most
+efficient way possible.
+
+In other words, this is bad and should be avoided at all costs:
+
+```ruby
+class User < ActiveRecord::Base
+ has_many :posts, dependent: :destroy
+end
+```
+
+Should you truly have a need for this it should be approved by a database
+specialist first.
+
+You should also not define any `before_destroy` or `after_destroy` callbacks on
+your models _unless_ absolutely required and only when approved by database
+specialists. For example, if each row in a table has a corresponding file on a
+file system it may be tempting to add a `after_destroy` hook. This however
+introduces non database logic to a model, and means we can no longer rely on
+foreign keys to remove the data as this would result in the filesystem data
+being left behind. In such a case you should use a service class instead that
+takes care of removing non database data.
diff --git a/doc/development/frontend.md b/doc/development/frontend.md
index f879cd57e25..f46cc377f95 100644
--- a/doc/development/frontend.md
+++ b/doc/development/frontend.md
@@ -1,225 +1,4 @@
-# Frontend Development Guidelines
-
-This document describes various guidelines to ensure consistency and quality
-across GitLab's frontend team.
-
-## Overview
-
-GitLab is built on top of [Ruby on Rails][rails] using [Haml][haml] with
-[Hamlit][hamlit]. Be wary of [the limitations that come with using
-Hamlit][hamlit-limits]. We also use [SCSS][scss] and plain JavaScript with
-[ES6 by way of Babel][es6].
-
-The asset pipeline is [Sprockets][sprockets], which handles the concatenation,
-minification, and compression of our assets.
-
-[jQuery][jquery] is used throughout the application's JavaScript, with
-[Vue.js][vue] for particularly advanced, dynamic elements.
-
-### Vue
-
-For more complex frontend features, we recommend using Vue.js. It shares
-some ideas with React.js as well as Angular.
-
-To get started with Vue, read through [their documentation][vue-docs].
-
-## Performance
-
-### Resources
-
-- [WebPage Test][web-page-test] for testing site loading time and size.
-- [Google PageSpeed Insights][pagespeed-insights] grades web pages and provides feedback to improve the page.
-- [Profiling with Chrome DevTools][google-devtools-profiling]
-- [Browser Diet][browser-diet] is a community-built guide that catalogues practical tips for improving web page performance.
-
-### Page-specific JavaScript
-
-Certain pages may require the use of a third party library, such as [d3][d3] for
-the User Activity Calendar and [Chart.js][chartjs] for the Graphs pages. These
-libraries increase the page size significantly, and impact load times due to
-bandwidth bottlenecks and the browser needing to parse more JavaScript.
-
-In cases where libraries are only used on a few specific pages, we use
-"page-specific JavaScript" to prevent the main `application.js` file from
-becoming unnecessarily large.
-
-Steps to split page-specific JavaScript from the main `application.js`:
-
-1. Create a directory for the specific page(s), e.g. `graphs/`.
-1. In that directory, create a `namespace_bundle.js` file, e.g. `graphs_bundle.js`.
-1. In `graphs_bundle.js` add the line `//= require_tree .`, this adds all other files in the directory to the bundle.
-1. Add any necessary libraries to `app/assets/javascripts/lib/`, all files directly descendant from this directory will be precompiled as separate assets, in this case `chart.js` would be added.
-1. Add the new "bundle" file to the list of precompiled assets in
-`config/application.rb`.
- - For example: `config.assets.precompile << "graphs/graphs_bundle.js"`.
-1. Move code reliant on these libraries into the `graphs` directory.
-1. In the relevant views, add the scripts to the page with the following:
-
-```haml
-- content_for :page_specific_javascripts do
- = page_specific_javascript_tag('lib/chart.js')
- = page_specific_javascript_tag('graphs/graphs_bundle.js')
-```
-
-The above loads `chart.js` and `graphs_bundle.js` for this page only. `chart.js`
-is separated from the bundle file so it can be cached separately from the bundle
-and reused for other pages that also rely on the library. For an example, see
-[this Haml file][page-specific-js-example].
-
-### Minimizing page size
-
-A smaller page size means the page loads faster (especially important on mobile
-and poor connections), the page is parsed more quickly by the browser, and less
-data is used for users with capped data plans.
-
-General tips:
-
-- Don't add new fonts.
-- Prefer font formats with better compression, e.g. WOFF2 is better than WOFF, which is better than TTF.
-- Compress and minify assets wherever possible (For CSS/JS, Sprockets does this for us).
-- If some functionality can reasonably be achieved without adding extra libraries, avoid them.
-- Use page-specific JavaScript as described above to dynamically load libraries that are only needed on certain pages.
-
-## Accessibility
-
-### Resources
-
-[Chrome Accessibility Developer Tools][chrome-accessibility-developer-tools]
-are useful for testing for potential accessibility problems in GitLab.
-
-Accessibility best-practices and more in-depth information is available on
-[the Audit Rules page][audit-rules] for the Chrome Accessibility Developer Tools.
-
-## Security
-
-### Resources
-
-[Mozilla’s HTTP Observatory CLI][observatory-cli] and the
-[Qualys SSL Labs Server Test][qualys-ssl] are good resources for finding
-potential problems and ensuring compliance with security best practices.
-
-<!-- Uncomment these sections when CSP/SRI are implemented.
-### Content Security Policy (CSP)
-Content Security Policy is a web standard that intends to mitigate certain
-forms of Cross-Site Scripting (XSS) as well as data injection.
-
-Content Security Policy rules should be taken into consideration when
-implementing new features, especially those that may rely on connection with
-external services.
-
-GitLab's CSP is used for the following:
-
-- Blocking plugins like Flash and Silverlight from running at all on our pages.
-- Blocking the use of scripts and stylesheets downloaded from external sources.
-- Upgrading `http` requests to `https` when possible.
-- Preventing `iframe` elements from loading in most contexts.
-
-Some exceptions include:
-
-- Scripts from Google Analytics and Piwik if either is enabled.
-- Connecting with GitHub, Bitbucket, GitLab.com, etc. to allow project importing.
-- Connecting with Google, Twitter, GitHub, etc. to allow OAuth authentication.
-
-We use [the Secure Headers gem][secure_headers] to enable Content
-Security Policy headers in the GitLab Rails app.
-
-Some resources on implementing Content Security Policy:
-
-- [MDN Article on CSP][mdn-csp]
-- [GitHub’s CSP Journey on the GitHub Engineering Blog][github-eng-csp]
-- The Dropbox Engineering Blog's series on CSP: [1][dropbox-csp-1], [2][dropbox-csp-2], [3][dropbox-csp-3], [4][dropbox-csp-4]
-
-### Subresource Integrity (SRI)
-
-Subresource Integrity prevents malicious assets from being provided by a CDN by
-guaranteeing that the asset downloaded is identical to the asset the server
-is expecting.
-
-The Rails app generates a unique hash of the asset, which is used as the
-asset's `integrity` attribute. The browser generates the hash of the asset
-on-load and will reject the asset if the hashes do not match.
-
-All CSS and JavaScript assets should use Subresource Integrity. For implementation details,
-see the documentation for [the Sprockets implementation of SRI][sprockets-sri].
-
-Some resources on implementing Subresource Integrity:
-
-- [MDN Article on SRI][mdn-sri]
-- [Subresource Integrity on the GitHub Engineering Blog][github-eng-sri]
-
--->
-
-### Including external resources
-
-External fonts, CSS, and JavaScript should never be used with the exception of
-Google Analytics and Piwik - and only when the instance has enabled it. Assets
-should always be hosted and served locally from the GitLab instance. Embedded
-resources via `iframes` should never be used except in certain circumstances
-such as with ReCaptcha, which cannot be used without an `iframe`.
-
-### Avoiding inline scripts and styles
-
-In order to protect users from [XSS vulnerabilities][xss], we will disable inline scripts in the future using Content Security Policy.
-
-While inline scripts can be useful, they're also a security concern. If
-user-supplied content is unintentionally left un-sanitized, malicious users can
-inject scripts into the web app.
-
-Inline styles should be avoided in almost all cases, they should only be used
-when no alternatives can be found. This allows reusability of styles as well as
-readability.
-
-## Style guides and linting
-
-See the relevant style guides for our guidelines and for information on linting:
-
-- [SCSS][scss-style-guide]
-
-## Testing
-
-Feature tests need to be written for all new features. Regression tests
-also need to be written for all bug fixes to prevent them from occurring
-again in the future.
-
-See [the Testing Standards and Style Guidelines](testing.md) for more
-information.
-
-## Supported browsers
-
-For our currently-supported browsers, see our [requirements][requirements].
+# Frontend Development Guidelines
-[rails]: http://rubyonrails.org/
-[haml]: http://haml.info/
-[hamlit]: https://github.com/k0kubun/hamlit
-[hamlit-limits]: https://github.com/k0kubun/hamlit/blob/master/REFERENCE.md#limitations
-[scss]: http://sass-lang.com/
-[es6]: https://babeljs.io/
-[sprockets]: https://github.com/rails/sprockets
-[jquery]: https://jquery.com/
-[vue]: http://vuejs.org/
-[vue-docs]: http://vuejs.org/guide/index.html
-[web-page-test]: http://www.webpagetest.org/
-[pagespeed-insights]: https://developers.google.com/speed/pagespeed/insights/
-[google-devtools-profiling]: https://developers.google.com/web/tools/chrome-devtools/profile/?hl=en
-[browser-diet]: https://browserdiet.com/
-[d3]: https://d3js.org/
-[chartjs]: http://www.chartjs.org/
-[page-specific-js-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/13bb9ed77f405c5f6ee4fdbc964ecf635c9a223f/app/views/projects/graphs/_head.html.haml#L6-8
-[chrome-accessibility-developer-tools]: https://github.com/GoogleChrome/accessibility-developer-tools
-[audit-rules]: https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules
-[observatory-cli]: https://github.com/mozilla/http-observatory-cli)
-[qualys-ssl]: https://www.ssllabs.com/ssltest/analyze.html
-[secure_headers]: https://github.com/twitter/secureheaders
-[mdn-csp]: https://developer.mozilla.org/en-US/docs/Web/Security/CSP
-[github-eng-csp]: http://githubengineering.com/githubs-csp-journey/
-[dropbox-csp-1]: https://blogs.dropbox.com/tech/2015/09/on-csp-reporting-and-filtering/
-[dropbox-csp-2]: https://blogs.dropbox.com/tech/2015/09/unsafe-inline-and-nonce-deployment/
-[dropbox-csp-3]: https://blogs.dropbox.com/tech/2015/09/csp-the-unexpected-eval/
-[dropbox-csp-4]: https://blogs.dropbox.com/tech/2015/09/csp-third-party-integrations-and-privilege-separation/
-[mdn-sri]: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
-[github-eng-sri]: http://githubengineering.com/subresource-integrity/
-[sprockets-sri]: https://github.com/rails/sprockets-rails#sri-support
-[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
-[scss-style-guide]: scss_styleguide.md
-[requirements]: ../install/requirements.md#supported-web-browsers
+This page has moved [here](fe_guide/index.md).
diff --git a/doc/development/gemfile.md b/doc/development/gemfile.md
new file mode 100644
index 00000000000..ec9718cea71
--- /dev/null
+++ b/doc/development/gemfile.md
@@ -0,0 +1,14 @@
+# `Gemfile` guidelines
+
+When adding a new entry to `Gemfile` or upgrading an existing dependency pay
+attention to the following rules.
+
+## No gems fetched from git repositories
+
+We do not allow gems that are fetched from git repositories. All gems have
+to be available in the RubyGems index. We want to minimize external build
+dependencies and build times.
+
+## License compliance
+
+Refer to [licensing guidelines](licensing.md) for ensuring license compliance.
diff --git a/doc/development/gitlab_architecture_diagram.png b/doc/development/gitlab_architecture_diagram.png
index 80e975718e0..378f7384574 100644
--- a/doc/development/gitlab_architecture_diagram.png
+++ b/doc/development/gitlab_architecture_diagram.png
Binary files differ
diff --git a/doc/development/gotchas.md b/doc/development/gotchas.md
index 159d5ce286d..565d4b33457 100644
--- a/doc/development/gotchas.md
+++ b/doc/development/gotchas.md
@@ -3,7 +3,7 @@
The purpose of this guide is to document potential "gotchas" that contributors
might encounter or should avoid during development of GitLab CE and EE.
-## Don't `describe` symbols
+## Do not `describe` symbols
Consider the following model spec:
@@ -32,73 +32,112 @@ spec/models/user_spec.rb|6 error| Failure/Error: u = described_class.new NoMeth
Except for the top-level `describe` block, always provide a String argument to
`describe`.
-## Don't `rescue Exception`
+## Do not assert against the absolute value of a sequence-generated attribute
-See ["Why is it bad style to `rescue Exception => e` in Ruby?"][Exception].
-
-_**Note:** This rule is [enforced automatically by
-Rubocop](https://gitlab.com/gitlab-org/gitlab-ce/blob/8-4-stable/.rubocop.yml#L911-914)._
+Consider the following factory:
-[Exception]: http://stackoverflow.com/q/10048173/223897
+```ruby
+FactoryGirl.define do
+ factory :label do
+ sequence(:title) { |n| "label#{n}" }
+ end
+end
+```
-## Don't use inline CoffeeScript/JavaScript in views
+Consider the following API spec:
-Using the inline `:coffee` or `:coffeescript` Haml filters comes with a
-performance overhead. Using inline JavaScript is not a good way to structure your code and should be avoided.
+```ruby
+require 'rails_helper'
-_**Note:** We've [removed these two filters](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/initializers/hamlit.rb)
-in an initializer._
+describe API::Labels do
+ it 'creates a first label' do
+ create(:label)
-### Further reading
+ get api("/projects/#{project.id}/labels", user)
-- Pull Request: [Replace CoffeeScript block into JavaScript in Views](https://git.io/vztMu)
-- Stack Overflow: [Why you should not write inline JavaScript](http://programmers.stackexchange.com/questions/86589/why-should-i-avoid-inline-scripting)
-- Stack Overflow: [Performance implications of using :coffescript filter inside HAML templates?](http://stackoverflow.com/a/17571242/223897)
+ expect(response).to have_http_status(200)
+ expect(json_response.first['name']).to eq('label1')
+ end
-## ID-based CSS selectors need to be a bit more specific
+ it 'creates a second label' do
+ create(:label)
-Normally, because HTML `id` attributes need to be unique to the page, it's
-perfectly fine to write some JavaScript like the following:
+ get api("/projects/#{project.id}/labels", user)
-```javascript
-$('#js-my-selector').hide();
+ expect(response).to have_http_status(200)
+ expect(json_response.first['name']).to eq('label1')
+ end
+end
```
-However, there's a feature of GitLab's Markdown processing that [automatically
-adds anchors to header elements][ToC Processing], with the `id` attribute being
-automatically generated based on the content of the header.
-
-Unfortunately, this feature makes it possible for user-generated content to
-create a header element with the same `id` attribute we're using in our
-selector, potentially breaking the JavaScript behavior. A user could break the
-above example with the following Markdown:
+When run, this spec doesn't do what we might expect:
-```markdown
-## JS My Selector
-```
+```sh
+1) API::API reproduce sequence issue creates a second label
+ Failure/Error: expect(json_response.first['name']).to eq('label1')
-Which gets converted to the following HTML:
+ expected: "label1"
+ got: "label2"
-```html
-<h2>
- <a id="js-my-selector" class="anchor" href="#js-my-selector" aria-hidden="true"></a>
- JS My Selector
-</h2>
+ (compared using ==)
```
-[ToC Processing]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-4-stable/lib/banzai/filter/table_of_contents_filter.rb#L31-37
+That's because FactoryGirl sequences are not reseted for each example.
+
+Please remember that sequence-generated values exist only to avoid having to
+explicitly set attributes that have a uniqueness constraint when using a factory.
### Solution
-The current recommended fix for this is to make our selectors slightly more
-specific:
+If you assert against a sequence-generated attribute's value, you should set it
+explicitly. Also, the value you set shouldn't match the sequence pattern.
+
+For instance, using our `:label` factory, writing `create(:label, title: 'foo')`
+is ok, but `create(:label, title: 'label1')` is not.
+
+Following is the fixed API spec:
-```javascript
-$('div#js-my-selector').hide();
+```ruby
+require 'rails_helper'
+
+describe API::Labels do
+ it 'creates a first label' do
+ create(:label, title: 'foo')
+
+ get api("/projects/#{project.id}/labels", user)
+
+ expect(response).to have_http_status(200)
+ expect(json_response.first['name']).to eq('foo')
+ end
+
+ it 'creates a second label' do
+ create(:label, title: 'bar')
+
+ get api("/projects/#{project.id}/labels", user)
+
+ expect(response).to have_http_status(200)
+ expect(json_response.first['name']).to eq('bar')
+ end
+end
```
+## Do not `rescue Exception`
+
+See ["Why is it bad style to `rescue Exception => e` in Ruby?"][Exception].
+
+_**Note:** This rule is [enforced automatically by
+Rubocop](https://gitlab.com/gitlab-org/gitlab-ce/blob/8-4-stable/.rubocop.yml#L911-914)._
+
+[Exception]: http://stackoverflow.com/q/10048173/223897
+
+## Do not use inline JavaScript in views
+
+Using the inline `:javascript` Haml filters comes with a
+performance overhead. Using inline JavaScript is not a good way to structure your code and should be avoided.
+
+_**Note:** We've [removed these two filters](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/initializers/hamlit.rb)
+in an initializer._
+
### Further reading
-- Issue: [Merge request ToC anchor conflicts with tabs](https://gitlab.com/gitlab-org/gitlab-ce/issues/3908)
-- Merge Request: [Make tab target selectors less naive](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2023)
-- Merge Request: [Make cross-project reference's clipboard target less naive](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2024)
+- Stack Overflow: [Why you should not write inline JavaScript](http://programmers.stackexchange.com/questions/86589/why-should-i-avoid-inline-scripting)
diff --git a/doc/development/i18n_guide.md b/doc/development/i18n_guide.md
new file mode 100644
index 00000000000..756535e28bc
--- /dev/null
+++ b/doc/development/i18n_guide.md
@@ -0,0 +1,256 @@
+# Internationalization for GitLab
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10669) in GitLab 9.2.
+
+For working with internationalization (i18n) we use
+[GNU gettext](https://www.gnu.org/software/gettext/) given it's the most used
+tool for this task and we have a lot of applications that will help us to work
+with it.
+
+## Setting up GitLab Development Kit (GDK)
+
+In order to be able to work on the [GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab-ce) project we must download and
+configure it through [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit), we can do it by following this [guide](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/set-up-gdk.md).
+
+Once we have the GitLab project ready we can start working on the
+translation of the project.
+
+## Tools
+
+We use a couple of gems:
+
+1. [`gettext_i18n_rails`](https://github.com/grosser/gettext_i18n_rails): this
+ gem allow us to translate content from models, views and controllers. Also
+ it gives us access to the following raketasks:
+ - `rake gettext:find`: Parses almost all the files from the
+ Rails application looking for content that has been marked for
+ translation. Finally, it updates the PO files with the new content that
+ it has found.
+ - `rake gettext:pack`: Processes the PO files and generates the
+ MO files that are binary and are finally used by the application.
+
+1. [`gettext_i18n_rails_js`](https://github.com/webhippie/gettext_i18n_rails_js):
+ this gem is useful to make the translations available in JavaScript. It
+ provides the following raketask:
+ - `rake gettext:po_to_json`: Reads the contents from the PO files and
+ generates JSON files containing all the available translations.
+
+1. PO editor: there are multiple applications that can help us to work with PO
+ files, a good option is [Poedit](https://poedit.net/download) which is
+ available for macOS, GNU/Linux and Windows.
+
+## Preparing a page for translation
+
+We basically have 4 types of files:
+
+1. Ruby files: basically Models and Controllers.
+1. HAML files: these are the view files.
+1. ERB files: used for email templates.
+1. JavaScript files: we mostly need to work with VUE JS templates.
+
+### Ruby files
+
+If there is a method or variable that works with a raw string, for instance:
+
+```ruby
+def hello
+ "Hello world!"
+end
+```
+
+Or:
+
+```ruby
+hello = "Hello world!"
+```
+
+You can easily mark that content for translation with:
+
+```ruby
+def hello
+ _("Hello world!")
+end
+```
+
+Or:
+
+```ruby
+hello = _("Hello world!")
+```
+
+### HAML files
+
+Given the following content in HAML:
+
+```haml
+%h1 Hello world!
+```
+
+You can mark that content for translation with:
+
+```haml
+%h1= _("Hello world!")
+```
+
+### ERB files
+
+Given the following content in ERB:
+
+```erb
+<h1>Hello world!</h1>
+```
+
+You can mark that content for translation with:
+
+```erb
+<h1><%= _("Hello world!") %></h1>
+```
+
+### JavaScript files
+
+In JavaScript we added the `__()` (double underscore parenthesis) function
+for translations.
+
+### Updating the PO files with the new content
+
+Now that the new content is marked for translation, we need to update the PO
+files with the following command:
+
+```sh
+bundle exec rake gettext:find
+```
+
+This command will update the `locale/**/gitlab.edit.po` file with the
+new content that the parser has found.
+
+New translations will be added with their default content and will be marked
+fuzzy. To use the translation, look for the `#, fuzzy` mention in `gitlab.edit.po`
+and remove it.
+
+We need to make sure we remove the `fuzzy` translations before generating the
+`locale/**/gitlab.po` file. When they aren't removed, the resulting `.po` will
+be treated as a binary file which could overwrite translations that were merged
+before the new translations.
+
+When we are just preparing a page to be translated, but not actually adding any
+translations. There's no need to generate `.po` files.
+
+Translations that aren't used in the source code anymore will be marked with
+`~#`; these can be removed to keep our translation files clutter-free.
+
+## Working with special content
+
+### Interpolation
+
+- In Ruby/HAML:
+
+ ```ruby
+ _("Hello %{name}") % { name: 'Joe' }
+ ```
+
+- In JavaScript: Not supported at this moment.
+
+### Plurals
+
+- In Ruby/HAML:
+
+ ```ruby
+ n_('Apple', 'Apples', 3) => 'Apples'
+ ```
+
+ Using interpolation:
+ ```ruby
+ n_("There is a mouse.", "There are %d mice.", size) % size
+ ```
+
+- In JavaScript:
+
+ ```js
+ n__('Apple', 'Apples', 3) => 'Apples'
+ ```
+
+ Using interpolation:
+
+ ```js
+ n__('Last day', 'Last %d days', 30) => 'Last 30 days'
+ ```
+
+### Namespaces
+
+Sometimes you need to add some context to the text that you want to translate
+(if the word occurs in a sentence and/or the word is ambiguous).
+
+- In Ruby/HAML:
+
+ ```ruby
+ s_('OpenedNDaysAgo|Opened')
+ ```
+
+ In case the translation is not found it will return `Opened`.
+
+- In JavaScript:
+
+ ```js
+ s__('OpenedNDaysAgo|Opened')
+ ```
+
+### Just marking content for parsing
+
+Sometimes there are some dynamic translations that can't be found by the
+parser when running `bundle exec 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 is also and alternative method to [translate messages from validation errors](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#option-a).
+
+## Adding a new language
+
+Let's suppose you want to add translations for a new language, let's say French.
+
+1. The first step is to register the new language in `lib/gitlab/i18n.rb`:
+
+ ```ruby
+ ...
+ AVAILABLE_LANGUAGES = {
+ ...,
+ 'fr' => 'Français'
+ }.freeze
+ ...
+ ```
+
+1. Next, you need to add the language:
+
+ ```sh
+ bundle exec rake gettext:add_language[fr]
+ ```
+
+ If you want to add a new language for a specific region, the command is similar,
+ you just need to separate the region with an underscore (`_`). For example:
+
+ ```sh
+ bundle exec rake gettext:add_language[en_GB]
+ ```
+
+ Please note that you need to specify the region part in capitals.
+
+1. Now that the language is added, a new directory has been created under the
+ path: `locale/fr/`. You can now start using your PO editor to edit the PO file
+ located in: `locale/fr/gitlab.edit.po`.
+
+1. After you're done updating the translations, you need to process the PO files
+ in order to generate the binary MO files and finally update the JSON files
+ containing the translations:
+
+ ```sh
+ bundle exec rake gettext:compile
+ ```
+
+1. In order to see the translated content we need to change our preferred language
+ which can be found under the user's **Settings** (`/profile`).
+
+1. After checking that the changes are ok, you can proceed to commit the new files.
+ For example:
+
+ ```sh
+ git add locale/fr/ app/assets/javascripts/locale/fr/
+ git commit -m "Add French translations for Cycle Analytics page"
+ ```
diff --git a/doc/development/img/cache-hit.svg b/doc/development/img/cache-hit.svg
new file mode 100644
index 00000000000..1c37693df2d
--- /dev/null
+++ b/doc/development/img/cache-hit.svg
@@ -0,0 +1,21 @@
+<svg version="1.1" id="mscgen_js-svg-__svg" class="mscgen_js-svg-__svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="976" height="310" viewBox="0 0 976 310"><desc>
+
+# Generated by mscgen_js - https://sverweij.github.io/mscgen_js
+msc {
+ # options
+ hscale="1.5";
+
+ # entities
+ c [label="Client", textbgcolor="lime"],
+ rails [label="Rails", textbgcolor="cyan"],
+ etag [label="EtagCaching", textbgcolor="orange"],
+ redis [label="Redis", textbgcolor="white"];
+
+ # arcs
+ c =&gt; rails [label="GET /projects/5/pipelines"];
+ rails =&gt; etag [label="GET /projects/5/pipelines"];
+ etag =&gt; redis [label="read(key = 'GET &lt;Etag&gt;')"];
+ redis =&gt; etag [label="cache hit", linecolor="green", textcolor="green"];
+ |||;
+ etag =&gt; c [label="304 Not Modified", linecolor="blue", textcolor="blue"];
+}</desc><defs><style type="text/css">svg.mscgen_js-svg-__svg{font-family:Helvetica,sans-serif;font-size:12px;font-weight:normal;font-style:normal;text-decoration:none;background-color:white;stroke:black;stroke-width:2;color:black}.mscgen_js-svg-__svg path, .mscgen_js-svg-__svg rect{fill:none;color:black;stroke:black}.mscgen_js-svg-__svg .label-text-background{fill:white;stroke:white;stroke-width:0}.mscgen_js-svg-__svg .bglayer{fill:white;stroke:white;stroke-width:0}.mscgen_js-svg-__svg line{stroke:black}.mscgen_js-svg-__svg .return, .mscgen_js-svg-__svg .comment{stroke-dasharray:5,3}.mscgen_js-svg-__svg .inline_expression_divider{stroke-dasharray:10,5}.mscgen_js-svg-__svg text{color:inherit;stroke:none;text-anchor:middle}.mscgen_js-svg-__svg text.entity-text{text-decoration:underline}.mscgen_js-svg-__svg text.anchor-start{text-anchor:start}.mscgen_js-svg-__svg .arrow-marker{overflow:visible}.mscgen_js-svg-__svg .arrow-style{stroke-width:1}.mscgen_js-svg-__svg .arcrow, .mscgen_js-svg-__svg .arcrowomit, .mscgen_js-svg-__svg .emphasised{stroke-linecap:butt}.mscgen_js-svg-__svg .arcrowomit{stroke-dasharray:2,2;}.mscgen_js-svg-__svg .box, .mscgen_js-svg-__svg .entity{fill:white;stroke-linejoin:round}.mscgen_js-svg-__svg .inherit{stroke:inherit;color:inherit}.mscgen_js-svg-__svg .inherit-fill{fill:inherit}.mscgen_js-svg-__svg .watermark{stroke:black;color:black;fill:black;font-size:48pt;font-weight:bold;opacity:0.14}</style><marker orient="auto" id="mscgen_js-svg-__svgmethod-black" class="arrow-marker" viewBox="0 0 10 10" refX="9" refY="3" markerUnits="strokeWidth" markerWidth="10" markerHeight="10"><polygon points="1,1 9,3 1,5" class="arrow-style" stroke="black" fill="black"></polygon></marker><marker orient="auto" id="mscgen_js-svg-__svgmethod-l-black" class="arrow-marker" viewBox="0 0 10 10" refX="9" refY="3" markerUnits="strokeWidth" markerWidth="10" markerHeight="10"><polygon points="17,1 9,3 17,5" class="arrow-style" stroke="black" fill="black"></polygon></marker><marker orient="auto" id="mscgen_js-svg-__svgmethod-blue" class="arrow-marker" viewBox="0 0 10 10" refX="9" refY="3" markerUnits="strokeWidth" markerWidth="10" markerHeight="10"><polygon points="1,1 9,3 1,5" class="arrow-style" stroke="blue" fill="blue"></polygon></marker><marker orient="auto" id="mscgen_js-svg-__svgmethod-l-blue" class="arrow-marker" viewBox="0 0 10 10" refX="9" refY="3" markerUnits="strokeWidth" markerWidth="10" markerHeight="10"><polygon points="17,1 9,3 17,5" class="arrow-style" stroke="blue" fill="blue"></polygon></marker><marker orient="auto" id="mscgen_js-svg-__svgmethod-green" class="arrow-marker" viewBox="0 0 10 10" refX="9" refY="3" markerUnits="strokeWidth" markerWidth="10" markerHeight="10"><polygon points="1,1 9,3 1,5" class="arrow-style" stroke="green" fill="green"></polygon></marker><marker orient="auto" id="mscgen_js-svg-__svgmethod-l-green" class="arrow-marker" viewBox="0 0 10 10" refX="9" refY="3" markerUnits="strokeWidth" markerWidth="10" markerHeight="10"><polygon points="17,1 9,3 17,5" class="arrow-style" stroke="green" fill="green"></polygon></marker></defs><g id="mscgen_js-svg-__svg__body" transform="translate(53,3) scale(1,1)"><g id="mscgen_js-svg-__svg__background"><rect width="976" height="310" x="-53" y="-3" class="bglayer"></rect></g><g id="mscgen_js-svg-__svg__arcspanlayer"></g><g id="mscgen_js-svg-__svg__lifelinelayer"><line x1="75" y1="38" x2="75" y2="76" class="arcrow"></line><line x1="315" y1="38" x2="315" y2="76" class="arcrow"></line><line x1="555" y1="38" x2="555" y2="76" class="arcrow"></line><line x1="795" y1="38" x2="795" y2="76" class="arcrow"></line><line x1="75" y1="76" x2="75" y2="114" class="arcrow"></line><line x1="315" y1="76" x2="315" y2="114" class="arcrow"></line><line x1="555" y1="76" x2="555" y2="114" class="arcrow"></line><line x1="795" y1="76" x2="795" y2="114" class="arcrow"></line><line x1="75" y1="114" x2="75" y2="152" class="arcrow"></line><line x1="315" y1="114" x2="315" y2="152" class="arcrow"></line><line x1="555" y1="114" x2="555" y2="152" class="arcrow"></line><line x1="795" y1="114" x2="795" y2="152" class="arcrow"></line><line x1="75" y1="152" x2="75" y2="190" class="arcrow"></line><line x1="315" y1="152" x2="315" y2="190" class="arcrow"></line><line x1="555" y1="152" x2="555" y2="190" class="arcrow"></line><line x1="795" y1="152" x2="795" y2="190" class="arcrow"></line><line x1="75" y1="190" x2="75" y2="228" class="arcrow"></line><line x1="315" y1="190" x2="315" y2="228" class="arcrow"></line><line x1="555" y1="190" x2="555" y2="228" class="arcrow"></line><line x1="795" y1="190" x2="795" y2="228" class="arcrow"></line><line x1="75" y1="228" x2="75" y2="266" class="arcrow"></line><line x1="315" y1="228" x2="315" y2="266" class="arcrow"></line><line x1="555" y1="228" x2="555" y2="266" class="arcrow"></line><line x1="795" y1="228" x2="795" y2="266" class="arcrow"></line><line x1="75" y1="266" x2="75" y2="304" class="arcrow"></line><line x1="315" y1="266" x2="315" y2="304" class="arcrow"></line><line x1="555" y1="266" x2="555" y2="304" class="arcrow"></line><line x1="795" y1="266" x2="795" y2="304" class="arcrow"></line></g><g id="mscgen_js-svg-__svg__sequencelayer"><g id="mscgen_js-svg-__svgentities"><g><rect width="150" height="38" class="entity" style="fill:lime;"></rect><g><text x="75" y="22.5" class="entity-text "><tspan>Client</tspan></text></g></g><g><rect width="150" height="38" x="240" class="entity" style="fill:cyan;"></rect><g><text x="315" y="22.5" class="entity-text "><tspan>Rails</tspan></text></g></g><g><rect width="150" height="38" x="480" class="entity" style="fill:orange;"></rect><g><text x="555" y="22.5" class="entity-text "><tspan>EtagCaching</tspan></text></g></g><g><rect width="150" height="38" x="720" class="entity" style="fill:white;"></rect><g><text x="795" y="22.5" class="entity-text "><tspan>Redis</tspan></text></g></g></g><g><line x1="75" y1="95" x2="315" y2="95" class="arc directional method" style="stroke:black" marker-end="url(#mscgen_js-svg-__svgmethod-black)"></line><g><rect width="134.06" height="14" x="127.97" y="79.5" class="label-text-background"></rect><text x="195" y="90.5" class="directional-text method-text "><tspan>GET /projects/5/pipelines</tspan></text></g></g><g><line x1="315" y1="133" x2="555" y2="133" class="arc directional method" style="stroke:black" marker-end="url(#mscgen_js-svg-__svgmethod-black)"></line><g><rect width="134.06" height="14" x="367.97" y="117.5" class="label-text-background"></rect><text x="435" y="128.5" class="directional-text method-text "><tspan>GET /projects/5/pipelines</tspan></text></g></g><g><line x1="555" y1="171" x2="795" y2="171" class="arc directional method" style="stroke:black" marker-end="url(#mscgen_js-svg-__svgmethod-black)"></line><g><rect width="135.64" height="14" x="607.17" y="155.5" class="label-text-background"></rect><text x="675" y="166.5" class="directional-text method-text "><tspan>read(key = 'GET &lt;Etag&gt;')</tspan></text></g></g><g><line x1="795" y1="209" x2="555" y2="209" class="arc directional method" style="stroke:green" marker-end="url(#mscgen_js-svg-__svgmethod-green)"></line><g><rect width="48.02" height="14" x="650.98" y="193.5" class="label-text-background"></rect><text x="675" y="204.5" class="directional-text method-text " style="fill:green;"><tspan>cache hit</tspan></text></g></g><g></g><g><line x1="555" y1="285" x2="75" y2="285" class="arc directional method" style="stroke:blue" marker-end="url(#mscgen_js-svg-__svgmethod-blue)"></line><g><rect width="90.72" height="14" x="269.63" y="269.5" class="label-text-background"></rect><text x="315" y="280.5" class="directional-text method-text " style="fill:blue;"><tspan>304 Not Modified</tspan></text></g></g></g><g id="mscgen_js-svg-__svg__notelayer"></g><g id="mscgen_js-svg-__svg__watermark"></g></g></svg> \ No newline at end of file
diff --git a/doc/development/img/cache-miss.svg b/doc/development/img/cache-miss.svg
new file mode 100644
index 00000000000..8429e6a1918
--- /dev/null
+++ b/doc/development/img/cache-miss.svg
@@ -0,0 +1,24 @@
+<svg version="1.1" id="mscgen_js-svg-__svg" class="mscgen_js-svg-__svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="976" height="386" viewBox="0 0 976 386"><desc>
+
+# Generated by mscgen_js - https://sverweij.github.io/mscgen_js
+msc {
+ # options
+ hscale="1.5";
+
+ # entities
+ c [label="Client", textbgcolor="lime"],
+ rails [label="Rails", textbgcolor="cyan"],
+ etag [label="EtagCaching", textbgcolor="orange"],
+ redis [label="Redis", textbgcolor="white"];
+
+ # arcs
+ c =&gt; rails [label="GET /projects/5/pipelines"];
+ rails =&gt; etag [label="GET /projects/5/pipelines"];
+ etag =&gt; redis [label="read(key = 'GET &lt;Etag&gt;')"];
+ redis =&gt; etag [label="cache miss", linecolor="red", textcolor="red"];
+ |||;
+ etag =&gt; redis [label="write('&lt;New Etag&gt;')"];
+ etag =&gt; rails [label="GET /projects/5/pipelines"];
+ rails =&gt; c [label="JSON response w/ ETag", linecolor="blue", textcolor="blue"];
+}
+</desc><defs><style type="text/css">svg.mscgen_js-svg-__svg{font-family:Helvetica,sans-serif;font-size:12px;font-weight:normal;font-style:normal;text-decoration:none;background-color:white;stroke:black;stroke-width:2}.mscgen_js-svg-__svg path, .mscgen_js-svg-__svg rect{fill:none}.mscgen_js-svg-__svg .label-text-background{fill:white;stroke:white;stroke-width:0}.mscgen_js-svg-__svg .bglayer{fill:white;stroke:white;stroke-width:0}.mscgen_js-svg-__svg line{}.mscgen_js-svg-__svg .return, .mscgen_js-svg-__svg .comment{stroke-dasharray:5,3}.mscgen_js-svg-__svg .inline_expression_divider{stroke-dasharray:10,5}.mscgen_js-svg-__svg text{color:inherit;stroke:none;text-anchor:middle}.mscgen_js-svg-__svg text.entity-text{text-decoration:underline}.mscgen_js-svg-__svg text.anchor-start{text-anchor:start}.mscgen_js-svg-__svg .arrow-marker{overflow:visible}.mscgen_js-svg-__svg .arrow-style{stroke-width:1}.mscgen_js-svg-__svg .arcrow, .mscgen_js-svg-__svg .arcrowomit, .mscgen_js-svg-__svg .emphasised{stroke-linecap:butt}.mscgen_js-svg-__svg .arcrowomit{stroke-dasharray:2,2}.mscgen_js-svg-__svg .box, .mscgen_js-svg-__svg .entity{fill:white;stroke-linejoin:round}.mscgen_js-svg-__svg .inherit{stroke:inherit;color:inherit}.mscgen_js-svg-__svg .inherit-fill{fill:inherit}.mscgen_js-svg-__svg .watermark{font-size:48pt;font-weight:bold;opacity:0.14}</style><marker orient="auto" id="mscgen_js-svg-__svgmethod-black" class="arrow-marker" viewBox="0 0 10 10" refX="9" refY="3" markerUnits="strokeWidth" markerWidth="10" markerHeight="10"><polygon points="1,1 9,3 1,5" class="arrow-style" stroke="black" fill="black"></polygon></marker><marker orient="auto" id="mscgen_js-svg-__svgmethod-l-black" class="arrow-marker" viewBox="0 0 10 10" refX="9" refY="3" markerUnits="strokeWidth" markerWidth="10" markerHeight="10"><polygon points="17,1 9,3 17,5" class="arrow-style" stroke="black" fill="black"></polygon></marker><marker orient="auto" id="mscgen_js-svg-__svgmethod-blue" class="arrow-marker" viewBox="0 0 10 10" refX="9" refY="3" markerUnits="strokeWidth" markerWidth="10" markerHeight="10"><polygon points="1,1 9,3 1,5" class="arrow-style" stroke="blue" fill="blue"></polygon></marker><marker orient="auto" id="mscgen_js-svg-__svgmethod-l-blue" class="arrow-marker" viewBox="0 0 10 10" refX="9" refY="3" markerUnits="strokeWidth" markerWidth="10" markerHeight="10"><polygon points="17,1 9,3 17,5" class="arrow-style" stroke="blue" fill="blue"></polygon></marker><marker orient="auto" id="mscgen_js-svg-__svgmethod-red" class="arrow-marker" viewBox="0 0 10 10" refX="9" refY="3" markerUnits="strokeWidth" markerWidth="10" markerHeight="10"><polygon points="1,1 9,3 1,5" class="arrow-style" stroke="red" fill="red"></polygon></marker><marker orient="auto" id="mscgen_js-svg-__svgmethod-l-red" class="arrow-marker" viewBox="0 0 10 10" refX="9" refY="3" markerUnits="strokeWidth" markerWidth="10" markerHeight="10"><polygon points="17,1 9,3 17,5" class="arrow-style" stroke="red" fill="red"></polygon></marker></defs><g id="mscgen_js-svg-__svg__body" transform="translate(53,3) scale(1,1)"><g id="mscgen_js-svg-__svg__background"><rect width="976" height="386" x="-53" y="-3" class="bglayer"></rect></g><g id="mscgen_js-svg-__svg__arcspanlayer"></g><g id="mscgen_js-svg-__svg__lifelinelayer"><line x1="75" y1="38" x2="75" y2="76" class="arcrow"></line><line x1="315" y1="38" x2="315" y2="76" class="arcrow"></line><line x1="555" y1="38" x2="555" y2="76" class="arcrow"></line><line x1="795" y1="38" x2="795" y2="76" class="arcrow"></line><line x1="75" y1="76" x2="75" y2="114" class="arcrow"></line><line x1="315" y1="76" x2="315" y2="114" class="arcrow"></line><line x1="555" y1="76" x2="555" y2="114" class="arcrow"></line><line x1="795" y1="76" x2="795" y2="114" class="arcrow"></line><line x1="75" y1="114" x2="75" y2="152" class="arcrow"></line><line x1="315" y1="114" x2="315" y2="152" class="arcrow"></line><line x1="555" y1="114" x2="555" y2="152" class="arcrow"></line><line x1="795" y1="114" x2="795" y2="152" class="arcrow"></line><line x1="75" y1="152" x2="75" y2="190" class="arcrow"></line><line x1="315" y1="152" x2="315" y2="190" class="arcrow"></line><line x1="555" y1="152" x2="555" y2="190" class="arcrow"></line><line x1="795" y1="152" x2="795" y2="190" class="arcrow"></line><line x1="75" y1="190" x2="75" y2="228" class="arcrow"></line><line x1="315" y1="190" x2="315" y2="228" class="arcrow"></line><line x1="555" y1="190" x2="555" y2="228" class="arcrow"></line><line x1="795" y1="190" x2="795" y2="228" class="arcrow"></line><line x1="75" y1="228" x2="75" y2="266" class="arcrow"></line><line x1="315" y1="228" x2="315" y2="266" class="arcrow"></line><line x1="555" y1="228" x2="555" y2="266" class="arcrow"></line><line x1="795" y1="228" x2="795" y2="266" class="arcrow"></line><line x1="75" y1="266" x2="75" y2="304" class="arcrow"></line><line x1="315" y1="266" x2="315" y2="304" class="arcrow"></line><line x1="555" y1="266" x2="555" y2="304" class="arcrow"></line><line x1="795" y1="266" x2="795" y2="304" class="arcrow"></line><line x1="75" y1="304" x2="75" y2="342" class="arcrow"></line><line x1="315" y1="304" x2="315" y2="342" class="arcrow"></line><line x1="555" y1="304" x2="555" y2="342" class="arcrow"></line><line x1="795" y1="304" x2="795" y2="342" class="arcrow"></line><line x1="75" y1="342" x2="75" y2="380" class="arcrow"></line><line x1="315" y1="342" x2="315" y2="380" class="arcrow"></line><line x1="555" y1="342" x2="555" y2="380" class="arcrow"></line><line x1="795" y1="342" x2="795" y2="380" class="arcrow"></line></g><g id="mscgen_js-svg-__svg__sequencelayer"><g id="mscgen_js-svg-__svgentities"><g><rect width="150" height="38" class="entity" style="fill:lime;"></rect><g><text x="75" y="22.5" class="entity-text "><tspan>Client</tspan></text></g></g><g><rect width="150" height="38" x="240" class="entity" style="fill:cyan;"></rect><g><text x="315" y="22.5" class="entity-text "><tspan>Rails</tspan></text></g></g><g><rect width="150" height="38" x="480" class="entity" style="fill:orange;"></rect><g><text x="555" y="22.5" class="entity-text "><tspan>EtagCaching</tspan></text></g></g><g><rect width="150" height="38" x="720" class="entity" style="fill:white;"></rect><g><text x="795" y="22.5" class="entity-text "><tspan>Redis</tspan></text></g></g></g><g><line x1="75" y1="95" x2="315" y2="95" class="arc directional method" style="stroke:black" marker-end="url(#mscgen_js-svg-__svgmethod-black)"></line><g><rect width="134.06" height="14" x="127.97" y="79.5" class="label-text-background"></rect><text x="195" y="90.5" class="directional-text method-text "><tspan>GET /projects/5/pipelines</tspan></text></g></g><g><line x1="315" y1="133" x2="555" y2="133" class="arc directional method" style="stroke:black" marker-end="url(#mscgen_js-svg-__svgmethod-black)"></line><g><rect width="134.06" height="14" x="367.97" y="117.5" class="label-text-background"></rect><text x="435" y="128.5" class="directional-text method-text "><tspan>GET /projects/5/pipelines</tspan></text></g></g><g><line x1="555" y1="171" x2="795" y2="171" class="arc directional method" style="stroke:black" marker-end="url(#mscgen_js-svg-__svgmethod-black)"></line><g><rect width="135.64" height="14" x="607.17" y="155.5" class="label-text-background"></rect><text x="675" y="166.5" class="directional-text method-text "><tspan>read(key = 'GET &lt;Etag&gt;')</tspan></text></g></g><g><line x1="795" y1="209" x2="555" y2="209" class="arc directional method" style="stroke:red" marker-end="url(#mscgen_js-svg-__svgmethod-red)"></line><g><rect width="60.02" height="14" x="644.98" y="193.5" class="label-text-background"></rect><text x="675" y="204.5" class="directional-text method-text " style="fill:red;"><tspan>cache miss</tspan></text></g></g><g></g><g><line x1="555" y1="285" x2="795" y2="285" class="arc directional method" style="stroke:black" marker-end="url(#mscgen_js-svg-__svgmethod-black)"></line><g><rect width="103.94" height="14" x="623.02" y="269.5" class="label-text-background"></rect><text x="675" y="280.5" class="directional-text method-text "><tspan>write('&lt;New Etag&gt;')</tspan></text></g></g><g><line x1="555" y1="323" x2="315" y2="323" class="arc directional method" style="stroke:black" marker-end="url(#mscgen_js-svg-__svgmethod-black)"></line><g><rect width="134.06" height="14" x="367.97" y="307.5" class="label-text-background"></rect><text x="435" y="318.5" class="directional-text method-text "><tspan>GET /projects/5/pipelines</tspan></text></g></g><g><line x1="315" y1="361" x2="75" y2="361" class="arc directional method" style="stroke:blue" marker-end="url(#mscgen_js-svg-__svgmethod-blue)"></line><g><rect width="130.72" height="14" x="129.63" y="345.5" class="label-text-background"></rect><text x="195" y="356.5" class="directional-text method-text " style="fill:blue;"><tspan>JSON response w/ ETag</tspan></text></g></g></g><g id="mscgen_js-svg-__svg__notelayer"></g><g id="mscgen_js-svg-__svg__watermark"></g></g></svg> \ No newline at end of file
diff --git a/doc/development/img/state-model-issue.png b/doc/development/img/state-model-issue.png
new file mode 100644
index 00000000000..ee33b6886c6
--- /dev/null
+++ b/doc/development/img/state-model-issue.png
Binary files differ
diff --git a/doc/development/img/state-model-legend.png b/doc/development/img/state-model-legend.png
new file mode 100644
index 00000000000..1c121f2588c
--- /dev/null
+++ b/doc/development/img/state-model-legend.png
Binary files differ
diff --git a/doc/development/img/state-model-merge-request.png b/doc/development/img/state-model-merge-request.png
new file mode 100644
index 00000000000..e00da10cac2
--- /dev/null
+++ b/doc/development/img/state-model-merge-request.png
Binary files differ
diff --git a/doc/development/img/trigger_ss1.png b/doc/development/img/trigger_ss1.png
new file mode 100644
index 00000000000..ccff1009a25
--- /dev/null
+++ b/doc/development/img/trigger_ss1.png
Binary files differ
diff --git a/doc/development/img/trigger_ss2.png b/doc/development/img/trigger_ss2.png
new file mode 100644
index 00000000000..94dfd048793
--- /dev/null
+++ b/doc/development/img/trigger_ss2.png
Binary files differ
diff --git a/doc/development/instrumentation.md b/doc/development/instrumentation.md
index 105e2f1242a..a14c0752366 100644
--- a/doc/development/instrumentation.md
+++ b/doc/development/instrumentation.md
@@ -24,7 +24,7 @@ namespace you can use the `configure` class method. This method simply yields
the supplied block while passing `Gitlab::Metrics::Instrumentation` as its
argument. An example:
-```
+```ruby
Gitlab::Metrics::Instrumentation.configure do |conf|
conf.instrument_method(Foo, :bar)
conf.instrument_method(Foo, :baz)
@@ -35,13 +35,13 @@ Using this method is in general preferred over directly calling the various
instrumentation methods.
Method instrumentation should be added in the initializer
-`config/initializers/metrics.rb`.
+`config/initializers/8_metrics.rb`.
### Examples
Instrumenting a single method:
-```
+```ruby
Gitlab::Metrics::Instrumentation.configure do |conf|
conf.instrument_method(User, :find_by)
end
@@ -49,7 +49,7 @@ end
Instrumenting an entire class hierarchy:
-```
+```ruby
Gitlab::Metrics::Instrumentation.configure do |conf|
conf.instrument_class_hierarchy(ActiveRecord::Base)
end
@@ -57,7 +57,7 @@ end
Instrumenting all public class methods:
-```
+```ruby
Gitlab::Metrics::Instrumentation.configure do |conf|
conf.instrument_methods(User)
end
@@ -68,7 +68,7 @@ end
The easiest way to check if a method has been instrumented is to check its
source location. For example:
-```
+```ruby
method = Rugged::TagCollection.instance_method(:[])
method.source_location
diff --git a/doc/development/licensing.md b/doc/development/licensing.md
index 05972b33fdb..1f115059fb8 100644
--- a/doc/development/licensing.md
+++ b/doc/development/licensing.md
@@ -62,6 +62,11 @@ Libraries with the following licenses are unacceptable for use:
- [GNU GPL][GPL] (version 1, [version 2][GPLv2], [version 3][GPLv3], or any future versions): GPL-licensed libraries cannot be linked to from non-GPL projects.
- [GNU AGPLv3][AGPLv3]: AGPL-licensed libraries cannot be linked to from non-GPL projects.
+- [Open Software License (OSL)][OSL]: is a copyleft license. In addition, the FSF [recommend against its use][OSL-GNU].
+
+## Requesting Approval for Licenses
+
+Libraries that are not listed in the [Acceptable Licenses][Acceptable-Licenses] or [Unacceptable Licenses][Unacceptable-Licenses] list can be submitted to the legal team for review. Please create an issue in the [Organization Repository][Org-Repo] and cc `@gl-legal`. After a decision has been made, the original requestor is responsible for updating this document.
## Notes
@@ -93,3 +98,8 @@ Gems which are included only in the "development" or "test" groups by Bundler ar
[AGPLv3]: http://choosealicense.com/licenses/agpl-3.0/
[GNU-GPL-FAQ]: http://www.gnu.org/licenses/gpl-faq.html#IfLibraryIsGPL
[OSI-GPL]: https://opensource.org/faq#linking-proprietary-code
+[OSL]: https://opensource.org/licenses/OSL-3.0
+[OSL-GNU]: https://www.gnu.org/licenses/license-list.en.html#OSL
+[Org-Repo]: https://gitlab.com/gitlab-com/organization
+[Acceptable-Licenses]: #acceptable-licenses
+[Unacceptable-Licenses]: #unacceptable-licenses
diff --git a/doc/development/limit_ee_conflicts.md b/doc/development/limit_ee_conflicts.md
new file mode 100644
index 00000000000..899be9eae4b
--- /dev/null
+++ b/doc/development/limit_ee_conflicts.md
@@ -0,0 +1,341 @@
+# Limit conflicts with EE when developing on CE
+
+This guide contains best-practices for avoiding conflicts between CE and EE.
+
+## Daily CE Upstream merge
+
+GitLab Community Edition is merged daily into the Enterprise Edition (look for
+the [`CE Upstream` merge requests]). The daily merge is currently done manually
+by four individuals.
+
+**If a developer pings you in a `CE Upstream` merge request for help with
+resolving conflicts, please help them because it means that you didn't do your
+job to reduce the conflicts nor to ease their resolution in the first place!**
+
+To avoid the conflicts beforehand when working on CE, there are a few tools and
+techniques that can help you:
+
+- know what are the usual types of conflicts and how to prevent them
+- the CI `rake ee_compat_check` job tells you if you need to open an EE-version
+ of your CE merge request
+
+[`CE Upstream` merge requests]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests?label_name%5B%5D=CE+upstream
+
+## Check the status of the CI `rake ee_compat_check` job
+
+For each commit (except on `master`), the `rake ee_compat_check` CI job tries to
+detect if the current branch's changes will conflict during the CE->EE merge.
+
+The job reports what files are conflicting and how to setup a merge request
+against EE. Here is roughly how it works:
+
+1. Generates the diff between your branch and current CE `master`
+1. Tries to apply it to current EE `master`
+1. If it applies cleanly, the job succeeds, otherwise...
+1. Detects a branch with the `-ee` suffix in EE
+1. If it exists, generate the diff between this branch and current EE `master`
+1. Tries to apply it to current EE `master`
+1. If it applies cleanly, the job succeeds
+
+In the case where the job fails, it means you should create a `<ce_branch>-ee`
+branch, push it to EE and open a merge request against EE `master`. At this
+point if you retry the failing job in your CE merge request, it should now pass.
+
+Notes:
+
+- This task is not a silver-bullet, its current goal is to bring awareness to
+ developers that their work needs to be ported to EE.
+- Community contributors shouldn't submit merge requests against EE, but
+ reviewers should take actions by either creating such EE merge request or
+ asking a GitLab developer to do it once the merge request is merged.
+- If you branch is more than 500 commits behind `master`, the job will fail and
+ you should rebase your branch upon latest `master`.
+- Code reviews for merge requests often consist of multiple iterations of
+ feedback and fixes. There is no need to update your EE MR after each
+ iteration. Instead, create an EE MR as soon as you see the
+ `rake ee_compat_check` job failing. After you receive the final acceptance
+ from a Maintainer (but before the CE MR is merged) update the EE MR.
+ This helps to identify significant conflicts sooner, but also reduces the
+ number of times you have to resolve conflicts.
+- You can use [`git rerere`](https://git-scm.com/blog/2010/03/08/rerere.html)
+ to avoid resolving the same conflicts multiple times.
+
+## Possible type of conflicts
+
+### Controllers
+
+#### List or arrays are augmented in EE
+
+In controllers, the most common type of conflict is with `before_action` that
+has a list of actions in CE but EE adds some actions to that list.
+
+The same problem often occurs for `params.require` / `params.permit` calls.
+
+##### Mitigations
+
+Separate CE and EE actions/keywords. For instance for `params.require` in
+`ProjectsController`:
+
+```ruby
+def project_params
+ params.require(:project).permit(project_params_ce)
+ # On EE, this is always:
+ # params.require(:project).permit(project_params_ce << project_params_ee)
+end
+
+# Always returns an array of symbols, created however best fits the use case.
+# It _should_ be sorted alphabetically.
+def project_params_ce
+ %i[
+ description
+ name
+ path
+ ]
+end
+
+# (On EE)
+def project_params_ee
+ %i[
+ approvals_before_merge
+ approver_group_ids
+ approver_ids
+ ...
+ ]
+end
+```
+
+#### Additional condition(s) in EE
+
+For instance for LDAP:
+
+```diff
+ def destroy
+ @key = current_user.keys.find(params[:id])
+ - @key.destroy
+ + @key.destroy unless @key.is_a? LDAPKey
+
+ respond_to do |format|
+```
+
+Or for Geo:
+
+```diff
+def after_sign_out_path_for(resource)
+- current_application_settings.after_sign_out_path.presence || new_user_session_path
++ if Gitlab::Geo.secondary?
++ Gitlab::Geo.primary_node.oauth_logout_url(@geo_logout_state)
++ else
++ current_application_settings.after_sign_out_path.presence || new_user_session_path
++ end
+end
+```
+
+Or even for audit log:
+
+```diff
+def approve_access_request
+- Members::ApproveAccessRequestService.new(membershipable, current_user, params).execute
++ member = Members::ApproveAccessRequestService.new(membershipable, current_user, params).execute
++
++ log_audit_event(member, action: :create)
+
+ redirect_to polymorphic_url([membershipable, :members])
+end
+```
+
+### Views
+
+#### Additional view code in EE
+
+A block of code added in CE conflicts because there is already another block
+at the same place in EE
+
+##### Mitigations
+
+Blocks of code that are EE-specific should be moved to partials as much as
+possible to avoid conflicts with big chunks of HAML code that that are not fun
+to resolve when you add the indentation to the equation.
+
+For instance this kind of thing:
+
+```haml
+.form-group.detail-page-description
+ = form.label :description, 'Description', class: 'control-label'
+ .col-sm-10
+ = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
+ = render 'projects/zen', f: form, attr: :description,
+ classes: 'note-textarea',
+ placeholder: "Write a comment or drag your files here...",
+ supports_quick_actions: !issuable.persisted?
+ = render 'projects/notes/hints', supports_quick_actions: !issuable.persisted?
+ .clearfix
+ .error-alert
+- if issuable.is_a?(Issue)
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = form.label :confidential do
+ = form.check_box :confidential
+ This issue is confidential and should only be visible to team members with at least Reporter access.
+- if can?(current_user, :"admin_#{issuable.to_ability_name}", issuable.project)
+ - has_due_date = issuable.has_attribute?(:due_date)
+ %hr
+ .row
+ %div{ class: (has_due_date ? "col-lg-6" : "col-sm-12") }
+ .form-group.issue-assignee
+ = form.label :assignee_id, "Assignee", class: "control-label #{"col-lg-4" if has_due_date}"
+ .col-sm-10{ class: ("col-lg-8" if has_due_date) }
+ .issuable-form-select-holder
+ - if issuable.assignee_id
+ = form.hidden_field :assignee_id
+ = dropdown_tag(user_dropdown_label(issuable.assignee_id, "Assignee"), options: { toggle_class: "js-dropdown-keep-input js-user-search js-issuable-form-dropdown js-assignee-search", title: "Select assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee js-filter-submit",
+ placeholder: "Search assignee", data: { first_user: current_user.try(:username), null_user: true, current_user: true, project_id: project.try(:id), selected: issuable.assignee_id, field_name: "#{issuable.class.model_name.param_key}[assignee_id]", default_label: "Assignee"} })
+ .form-group.issue-milestone
+ = form.label :milestone_id, "Milestone", class: "control-label #{"col-lg-4" if has_due_date}"
+ .col-sm-10{ class: ("col-lg-8" if has_due_date) }
+ .issuable-form-select-holder
+ = render "shared/issuable/milestone_dropdown", selected: issuable.milestone, name: "#{issuable.class.model_name.param_key}[milestone_id]", show_any: false, show_upcoming: false, extra_class: "js-issuable-form-dropdown js-dropdown-keep-input", dropdown_title: "Select milestone"
+ .form-group
+ - has_labels = @labels && @labels.any?
+ = form.label :label_ids, "Labels", class: "control-label #{"col-lg-4" if has_due_date}"
+ = form.hidden_field :label_ids, multiple: true, value: ''
+ .col-sm-10{ class: "#{"col-lg-8" if has_due_date} #{'issuable-form-padding-top' if !has_labels}" }
+ .issuable-form-select-holder
+ = render "shared/issuable/label_dropdown", classes: ["js-issuable-form-dropdown"], selected: issuable.labels, data_options: { field_name: "#{issuable.class.model_name.param_key}[label_ids][]", show_any: false }, dropdown_title: "Select label"
+ - if issuable.respond_to?(:weight)
+ - weight_options = Issue.weight_options
+ - weight_options.delete(Issue::WEIGHT_ALL)
+ - weight_options.delete(Issue::WEIGHT_ANY)
+ .form-group
+ = form.label :label_ids, class: "control-label #{"col-lg-4" if has_due_date}" do
+ Weight
+ .col-sm-10{ class: ("col-lg-8" if has_due_date) }
+ .issuable-form-select-holder
+ - if issuable.weight
+ = form.hidden_field :weight
+ = dropdown_tag(issuable.weight || "Weight", options: { title: "Select weight", toggle_class: 'js-weight-select js-issuable-form-weight', dropdown_class: "dropdown-menu-selectable dropdown-menu-weight",
+ placeholder: "Search weight", data: { field_name: "#{issuable.class.model_name.param_key}[weight]" , default_label: "Weight" } }) do
+ %ul
+ - weight_options.each do |weight|
+ %li
+ %a{href: "#", data: { id: weight, none: weight === Issue::WEIGHT_NONE }, class: ("is-active" if issuable.weight == weight)}
+ = weight
+ - if has_due_date
+ .col-lg-6
+ .form-group
+ = form.label :due_date, "Due date", class: "control-label"
+ .col-sm-10
+ .issuable-form-select-holder
+ = form.text_field :due_date, id: "issuable-due-date", class: "datepicker form-control", placeholder: "Select due date"
+```
+
+could be simplified by using partials:
+
+```haml
+= render 'shared/issuable/form/description', issuable: issuable, form: form
+
+- if issuable.respond_to?(:confidential)
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = form.label :confidential do
+ = form.check_box :confidential
+ This issue is confidential and should only be visible to team members with at least Reporter access.
+
+= render 'shared/issuable/form/metadata', issuable: issuable, form: form
+```
+
+and then the `app/views/shared/issuable/form/_metadata.html.haml` could be as follows:
+
+```haml
+- issuable = local_assigns.fetch(:issuable)
+
+- return unless can?(current_user, :"admin_#{issuable.to_ability_name}", issuable.project)
+
+- has_due_date = issuable.has_attribute?(:due_date)
+- has_labels = @labels && @labels.any?
+- form = local_assigns.fetch(:form)
+
+%hr
+.row
+ %div{ class: (has_due_date ? "col-lg-6" : "col-sm-12") }
+ .form-group.issue-assignee
+ = form.label :assignee_id, "Assignee", class: "control-label #{"col-lg-4" if has_due_date}"
+ .col-sm-10{ class: ("col-lg-8" if has_due_date) }
+ .issuable-form-select-holder
+ - if issuable.assignee_id
+ = form.hidden_field :assignee_id
+ = dropdown_tag(user_dropdown_label(issuable.assignee_id, "Assignee"), options: { toggle_class: "js-dropdown-keep-input js-user-search js-issuable-form-dropdown js-assignee-search", title: "Select assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee js-filter-submit",
+ placeholder: "Search assignee", data: { first_user: current_user.try(:username), null_user: true, current_user: true, project_id: issuable.project.try(:id), selected: issuable.assignee_id, field_name: "#{issuable.class.model_name.param_key}[assignee_id]", default_label: "Assignee"} })
+ .form-group.issue-milestone
+ = form.label :milestone_id, "Milestone", class: "control-label #{"col-lg-4" if has_due_date}"
+ .col-sm-10{ class: ("col-lg-8" if has_due_date) }
+ .issuable-form-select-holder
+ = render "shared/issuable/milestone_dropdown", selected: issuable.milestone, name: "#{issuable.class.model_name.param_key}[milestone_id]", show_any: false, show_upcoming: false, extra_class: "js-issuable-form-dropdown js-dropdown-keep-input", dropdown_title: "Select milestone"
+ .form-group
+ - has_labels = @labels && @labels.any?
+ = form.label :label_ids, "Labels", class: "control-label #{"col-lg-4" if has_due_date}"
+ = form.hidden_field :label_ids, multiple: true, value: ''
+ .col-sm-10{ class: "#{"col-lg-8" if has_due_date} #{'issuable-form-padding-top' if !has_labels}" }
+ .issuable-form-select-holder
+ = render "shared/issuable/label_dropdown", classes: ["js-issuable-form-dropdown"], selected: issuable.labels, data_options: { field_name: "#{issuable.class.model_name.param_key}[label_ids][]", show_any: false }, dropdown_title: "Select label"
+
+ = render "shared/issuable/form/weight", issuable: issuable, form: form
+
+ - if has_due_date
+ .col-lg-6
+ .form-group
+ = form.label :due_date, "Due date", class: "control-label"
+ .col-sm-10
+ .issuable-form-select-holder
+ = form.text_field :due_date, id: "issuable-due-date", class: "datepicker form-control", placeholder: "Select due date"
+```
+
+and then the `app/views/shared/issuable/form/_weight.html.haml` could be as follows:
+
+```haml
+- issuable = local_assigns.fetch(:issuable)
+
+- return unless issuable.respond_to?(:weight)
+
+- has_due_date = issuable.has_attribute?(:due_date)
+- form = local_assigns.fetch(:form)
+
+.form-group
+ = form.label :label_ids, class: "control-label #{"col-lg-4" if has_due_date}" do
+ Weight
+ .col-sm-10{ class: ("col-lg-8" if has_due_date) }
+ .issuable-form-select-holder
+ - if issuable.weight
+ = form.hidden_field :weight
+
+ = weight_dropdown_tag(issuable, toggle_class: 'js-issuable-form-weight') do
+ %ul
+ - Issue.weight_options.each do |weight|
+ %li
+ %a{ href: '#', data: { id: weight, none: weight === Issue::WEIGHT_NONE }, class: ("is-active" if issuable.weight == weight) }
+ = weight
+```
+
+Note:
+
+- The safeguards at the top allow to get rid of an unneccessary indentation level
+- Here we only moved the 'Weight' code to a partial since this is the only
+ EE-specific code in that view, so it's the most likely to conflict, but you
+ are encouraged to use partials even for code that's in CE to logically split
+ big views into several smaller files.
+
+#### Indentation issue
+
+Sometimes a code block is indented more or less in EE because there's an
+additional condition.
+
+##### Mitigations
+
+Blocks of code that are EE-specific should be moved to partials as much as
+possible to avoid conflicts with big chunks of HAML code that that are not fun
+to resolve when you add the indentation in the equation.
+
+---
+
+[Return to Development documentation](README.md)
diff --git a/doc/development/merge_request_performance_guidelines.md b/doc/development/merge_request_performance_guidelines.md
index 0363bf8c1d5..2b4126b43ef 100644
--- a/doc/development/merge_request_performance_guidelines.md
+++ b/doc/development/merge_request_performance_guidelines.md
@@ -3,7 +3,7 @@
To ensure a merge request does not negatively impact performance of GitLab
_every_ merge request **must** adhere to the guidelines outlined in this
document. There are no exceptions to this rule unless specifically discussed
-with and agreed upon by merge request endbosses and performance specialists.
+with and agreed upon by backend maintainers and performance specialists.
To measure the impact of a merge request you can use
[Sherlock](profiling.md#sherlock). It's also highly recommended that you read
@@ -40,9 +40,9 @@ section below for more information.
about the impact.
Sometimes it's hard to assess the impact of a merge request. In this case you
-should ask one of the merge request (mini) endbosses to review your changes. You
-can find a list of these endbosses at <https://about.gitlab.com/team/>. An
-endboss in turn can request a performance specialist to review the changes.
+should ask one of the merge request reviewers to review your changes. You can
+find a list of these reviewers at <https://about.gitlab.com/team/>. A reviewer
+in turn can request a performance specialist to review the changes.
## Query Counts
@@ -68,7 +68,7 @@ end
This will end up running one query for every object to update. This code can
easily overload a database given enough rows to update or many instances of this
code running in parallel. This particular problem is known as the
-["N+1 query problem"](http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations).
+["N+1 query problem"](http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations). You can write a test with [QueryRecoder](query_recorder.md) to detect this and prevent regressions.
In this particular case the workaround is fairly easy:
@@ -117,6 +117,8 @@ Post.all.includes(:author).each do |post|
end
```
+Also consider using [QueryRecoder tests](query_recorder.md) to prevent a regression when eager loading.
+
## Memory Usage
**Summary:** merge requests **must not** increase memory usage unless absolutely
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 61b0fbc89c9..161d2544169 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -4,28 +4,53 @@ When writing migrations for GitLab, you have to take into account that
these will be ran by hundreds of thousands of organizations of all sizes, some with
many years of data in their database.
-In addition, having to take a server offline for a an upgrade small or big is
-a big burden for most organizations. For this reason it is important that your
-migrations are written carefully, can be applied online and adhere to the style guide below.
+In addition, having to take a server offline for a a upgrade small or big is a
+big burden for most organizations. For this reason it is important that your
+migrations are written carefully, can be applied online and adhere to the style
+guide below.
-Migrations should not require GitLab installations to be taken offline unless
-_absolutely_ necessary - see the ["What Requires Downtime?"](what_requires_downtime.md)
-page. If a migration requires downtime, this should be clearly mentioned during
-the review process, as well as being documented in the monthly release post. For
-more information, see the "Downtime Tagging" section below.
+Migrations are **not** allowed to require GitLab installations to be taken
+offline unless _absolutely necessary_. Downtime assumptions should be based on
+the behaviour of a migration when performed using PostgreSQL, as various
+operations in MySQL may require downtime without there being alternatives.
+
+When downtime is necessary the migration has to be approved by:
+
+1. The VP of Engineering
+1. A Backend Lead
+1. A Database Specialist
+
+An up-to-date list of people holding these titles can be found at
+<https://about.gitlab.com/team/>.
+
+The document ["What Requires Downtime?"](what_requires_downtime.md) specifies
+various database operations, whether they require downtime and how to
+work around that whenever possible.
When writing your migrations, also consider that databases might have stale data
-or inconsistencies and guard for that. Try to make as little assumptions as possible
-about the state of the database.
+or inconsistencies and guard for that. Try to make as few assumptions as
+possible about the state of the database.
+
+Please don't depend on GitLab-specific code since it can change in future
+versions. If needed copy-paste GitLab code into the migration to make it forward
+compatible.
+
+## Commit Guidelines
-Please don't depend on GitLab specific code since it can change in future versions.
-If needed copy-paste GitLab code into the migration to make it forward compatible.
+Each migration **must** be added in its own commit with a descriptive commit
+message. If a commit adds a migration it _should only_ include the migration and
+any corresponding changes to `db/schema.rb`. This makes it easy to revert a
+database migration without accidentally reverting other changes.
## Downtime Tagging
Every migration must specify if it requires downtime or not, and if it should
-require downtime it must also specify a reason for this. To do so, add the
-following two constants to the migration class' body:
+require downtime it must also specify a reason for this. This is required even
+if 99% of the migrations won't require downtime as this makes it easier to find
+the migrations that _do_ require downtime.
+
+To tag a migration, add the following two constants to the migration class'
+body:
* `DOWNTIME`: a boolean that when set to `true` indicates the migration requires
downtime.
@@ -50,23 +75,79 @@ from a migration class.
## Reversibility
-Your migration should be reversible. This is very important, as it should
+Your migration **must be** reversible. This is very important, as it should
be possible to downgrade in case of a vulnerability or bugs.
In your migration, add a comment describing how the reversibility of the
migration was tested.
-## Removing indices
+## Multi Threading
-If you need to remove index, please add a condition like in following example:
+Sometimes a migration might need to use multiple Ruby threads to speed up a
+migration. For this to work your migration needs to include the module
+`Gitlab::Database::MultiThreadedMigration`:
+```ruby
+class MyMigration < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+ include Gitlab::Database::MultiThreadedMigration
+end
+```
+
+You can then use the method `with_multiple_threads` to perform work in separate
+threads. For example:
+
+```ruby
+class MyMigration < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+ include Gitlab::Database::MultiThreadedMigration
+
+ def up
+ with_multiple_threads(4) do
+ disable_statement_timeout
+
+ # ...
+ end
+ end
+end
```
-remove_index :namespaces, column: :name if index_exists?(:namespaces, :name)
+
+Here the call to `disable_statement_timeout` will use the connection local to
+the `with_multiple_threads` block, instead of re-using the global connection
+pool. This ensures each thread has its own connection object, and won't time
+out when trying to obtain one.
+
+**NOTE:** PostgreSQL has a maximum amount of connections that it allows. This
+limit can vary from installation to installation. As a result it's recommended
+you do not use more than 32 threads in a single migration. Usually 4-8 threads
+should be more than enough.
+
+## Removing indexes
+
+When removing an index make sure to use the method `remove_concurrent_index` instead
+of the regular `remove_index` method. The `remove_concurrent_index` method
+automatically drops concurrent indexes when using PostgreSQL, removing the
+need for downtime. To use this method you must disable transactions by calling
+the method `disable_ddl_transaction!` in the body of your migration class like
+so:
+
+```ruby
+class MyMigration < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index :table_name, :column_name if index_exists?(:table_name, :column_name)
+ end
+end
```
-## Adding indices
+## Adding indexes
-If you need to add an unique index please keep in mind there is possibility of existing duplicates. If it is possible write a separate migration for handling this situation. It can be just removing or removing with overwriting all references to these duplicates depend on situation.
+If you need to add a unique index please keep in mind there is the possibility
+of existing duplicates being present in the database. This means that should
+always _first_ add a migration that removes any duplicates, before adding the
+unique index.
When adding an index make sure to use the method `add_concurrent_index` instead
of the regular `add_index` method. The `add_concurrent_index` method
@@ -75,20 +156,25 @@ need for downtime. To use this method you must disable transactions by calling
the method `disable_ddl_transaction!` in the body of your migration class like
so:
-```
+```ruby
class MyMigration < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
+
disable_ddl_transaction!
- def change
+ def up
+ add_concurrent_index :table, :column
+ end
+ def down
+ remove_index :table, :column if index_exists?(:table, :column)
end
end
```
## Adding Columns With Default Values
-When adding columns with default values you should use the method
+When adding columns with default values you must use the method
`add_column_with_default`. This method ensures the table is updated without
requiring downtime. This method is not reversible so you must manually define
the `up` and `down` methods in your migration class.
@@ -96,7 +182,7 @@ the `up` and `down` methods in your migration class.
For example, to add the column `foo` to the `projects` table with a default
value of `10` you'd write the following:
-```
+```ruby
class MyMigration < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
@@ -111,6 +197,9 @@ class MyMigration < ActiveRecord::Migration
end
```
+Keep in mind that this operation can easily take 10-15 minutes to complete on
+larger installations (e.g. GitLab.com). As a result you should only add default
+values if absolutely necessary.
## Integer column type
@@ -125,7 +214,7 @@ set the limit to 8-bytes. This will allow the column to hold a value up to
Rails migration example:
-```
+```ruby
add_column_with_default(:projects, :foo, :integer, default: 10, limit: 8)
# or
@@ -133,19 +222,56 @@ add_column_with_default(:projects, :foo, :integer, default: 10, limit: 8)
add_column(:projects, :foo, :integer, default: 10, limit: 8)
```
+## Timestamp column type
+
+By default, Rails uses the `timestamp` data type that stores timestamp data without timezone information.
+The `timestamp` data type is used by calling either the `add_timestamps` or the `timestamps` method.
+Also Rails converts the `:datetime` data type to the `timestamp` one.
+
+Example:
+
+```ruby
+# timestamps
+create_table :users do |t|
+ t.timestamps
+end
+
+# add_timestamps
+def up
+ add_timestamps :users
+end
+
+# :datetime
+def up
+ add_column :users, :last_sign_in, :datetime
+end
+```
+
+Instead of using these methods one should use the following methods to store timestamps with timezones:
+
+* `add_timestamps_with_timezone`
+* `timestamps_with_timezone`
+
+This ensures all timestamps have a time zone specified. This in turn means existing timestamps won't
+suddenly use a different timezone when the system's timezone changes. It also makes it very clear which
+timezone was used in the first place.
+
+
## Testing
-Make sure that your migration works with MySQL and PostgreSQL with data. An empty database does not guarantee that your migration is correct.
+Make sure that your migration works with MySQL and PostgreSQL with data. An
+empty database does not guarantee that your migration is correct.
Make sure your migration can be reversed.
## Data migration
-Please prefer Arel and plain SQL over usual ActiveRecord syntax. In case of using plain SQL you need to quote all input manually with `quote_string` helper.
+Please prefer Arel and plain SQL over usual ActiveRecord syntax. In case of
+using plain SQL you need to quote all input manually with `quote_string` helper.
Example with Arel:
-```
+```ruby
users = Arel::Table.new(:users)
users.group(users[:user_id]).having(users[:id].count.gt(5))
@@ -154,7 +280,7 @@ users.group(users[:user_id]).having(users[:id].count.gt(5))
Example with plain SQL and `quote_string` helper:
-```
+```ruby
select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(id) > 1").each do |tag|
tag_name = quote_string(tag["name"])
duplicate_ids = select_all("SELECT id FROM tags WHERE name = '#{tag_name}'").map{|tag| tag["id"]}
@@ -165,3 +291,42 @@ select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(i
execute("DELETE FROM tags WHERE id IN(#{duplicate_ids.join(",")})")
end
```
+
+If you need more complex logic you can define and use models local to a
+migration. For example:
+
+```ruby
+class MyMigration < ActiveRecord::Migration
+ class Project < ActiveRecord::Base
+ self.table_name = 'projects'
+ end
+end
+```
+
+When doing so be sure to explicitly set the model's table name so it's not
+derived from the class name or namespace.
+
+### Renaming reserved paths
+
+When a new route for projects is introduced that could conflict with any
+existing records. The path for this records should be renamed, and the
+related data should be moved on disk.
+
+Since we had to do this a few times already, there are now some helpers to help
+with this.
+
+To use this you can include `Gitlab::Database::RenameReservedPathsMigration::V1`
+in your migration. This will provide 3 methods which you can pass one or more
+paths that need to be rejected.
+
+**`rename_root_paths`**: This will rename the path of all _namespaces_ with the
+given name that don't have a `parent_id`.
+
+**`rename_child_paths`**: This will rename the path of all _namespaces_ with the
+given name that have a `parent_id`.
+
+**`rename_wildcard_paths`**: This will rename the path of all _projects_, and all
+_namespaces_ that have a `project_id`.
+
+The `path` column for these rows will be renamed to their previous value followed
+by an integer. For example: `users` would turn into `users0`
diff --git a/doc/development/object_state_models.md b/doc/development/object_state_models.md
new file mode 100644
index 00000000000..623bbf143ef
--- /dev/null
+++ b/doc/development/object_state_models.md
@@ -0,0 +1,25 @@
+# Object state models
+
+## Diagrams
+
+[GitLab object state models](https://drive.google.com/drive/u/3/folders/0B5tDlHAM4iZINmpvYlJXcDVqMGc)
+
+---
+
+## Legend
+
+![legend](img/state-model-legend.png)
+
+---
+
+## Issue
+
+[`app/models/issue.rb`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/models/issue.rb)
+![issue](img/state-model-issue.png)
+
+---
+
+## Merge request
+
+[`app/models/merge_request.rb`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/models/merge_request.rb)
+![merge request](img/state-model-merge-request.png) \ No newline at end of file
diff --git a/doc/development/performance.md b/doc/development/performance.md
index 7ff603e2c4a..04419650b12 100644
--- a/doc/development/performance.md
+++ b/doc/development/performance.md
@@ -34,10 +34,12 @@ graphs/dashboards.
## Tooling
-GitLab provides two built-in tools to aid the process of improving performance:
+GitLab provides built-in tools to aid the process of improving performance:
* [Sherlock](profiling.md#sherlock)
-* [GitLab Performance Monitoring](../monitoring/performance/monitoring.md)
+* [GitLab Performance Monitoring](../administration/monitoring/performance/introduction.md)
+* [Request Profiling](../administration/monitoring/performance/request_profiling.md)
+* [QueryRecoder](query_recorder.md) for preventing `N+1` regressions
GitLab employees can use GitLab.com's performance monitoring systems located at
<http://performance.gitlab.net>, this requires you to log in using your
@@ -100,6 +102,151 @@ In short:
5. If you must write a benchmark use the benchmark-ips Gem instead of Ruby's
`Benchmark` module.
+## Profiling
+
+By collecting snapshots of process state at regular intervals, profiling allows
+you to see where time is spent in a process. The [StackProf](https://github.com/tmm1/stackprof)
+gem is included in GitLab's development environment, allowing you to investigate
+the behaviour of suspect code in detail.
+
+It's important to note that profiling an application *alters its performance*,
+and will generally be done *in an unrepresentative environment*. In particular,
+a method is not necessarily troublesome just because it is executed many times,
+or takes a long time to execute. Profiles are tools you can use to better
+understand what is happening in an application - using that information wisely
+is up to you!
+
+Keeping that in mind, to create a profile, identify (or create) a spec that
+exercises the troublesome code path, then run it using the `bin/rspec-stackprof`
+helper, e.g.:
+
+```
+$ LIMIT=10 bin/rspec-stackprof spec/policies/project_policy_spec.rb
+8/8 |====== 100 ======>| Time: 00:00:18
+
+Finished in 18.19 seconds (files took 4.8 seconds to load)
+8 examples, 0 failures
+
+==================================
+ Mode: wall(1000)
+ Samples: 17033 (5.59% miss rate)
+ GC: 1901 (11.16%)
+==================================
+ TOTAL (pct) SAMPLES (pct) FRAME
+ 6000 (35.2%) 2566 (15.1%) Sprockets::Cache::FileStore#get
+ 2018 (11.8%) 888 (5.2%) ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#exec_no_cache
+ 1338 (7.9%) 640 (3.8%) ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements#execute
+ 3125 (18.3%) 394 (2.3%) Sprockets::Cache::FileStore#safe_open
+ 913 (5.4%) 301 (1.8%) ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#exec_cache
+ 288 (1.7%) 288 (1.7%) ActiveRecord::Attribute#initialize
+ 246 (1.4%) 246 (1.4%) Sprockets::Cache::FileStore#safe_stat
+ 295 (1.7%) 193 (1.1%) block (2 levels) in class_attribute
+ 187 (1.1%) 187 (1.1%) block (4 levels) in class_attribute
+```
+
+You can limit the specs that are run by passing any arguments `rspec` would
+normally take.
+
+The output is sorted by the `Samples` column by default. This is the number of
+samples taken where the method is the one currently being executed. The `Total`
+column shows the number of samples taken where the method, or any of the methods
+it calls, were being executed.
+
+To create a graphical view of the call stack:
+
+```shell
+$ stackprof tmp/project_policy_spec.rb.dump --graphviz > project_policy_spec.dot
+$ dot -Tsvg project_policy_spec.dot > project_policy_spec.svg
+```
+
+To load the profile in [kcachegrind](https://kcachegrind.github.io/):
+
+```
+$ stackprof tmp/project_policy_spec.dump --callgrind > project_policy_spec.callgrind
+$ kcachegrind project_policy_spec.callgrind # Linux
+$ qcachegrind project_policy_spec.callgrind # Mac
+```
+
+It may be useful to zoom in on a specific method, e.g.:
+
+```
+$ stackprof tmp/project_policy_spec.rb.dump --method warm_asset_cache
+TestEnv#warm_asset_cache (/Users/lupine/dev/gitlab.com/gitlab-org/gitlab-development-kit/gitlab/spec/support/test_env.rb:164)
+ samples: 0 self (0.0%) / 6288 total (36.9%)
+ callers:
+ 6288 ( 100.0%) block (2 levels) in <top (required)>
+ callees (6288 total):
+ 6288 ( 100.0%) Capybara::RackTest::Driver#visit
+ code:
+ | 164 | def warm_asset_cache
+ | 165 | return if warm_asset_cache?
+ | 166 | return unless defined?(Capybara)
+ | 167 |
+ 6288 (36.9%) | 168 | Capybara.current_session.driver.visit '/'
+ | 169 | end
+$ stackprof tmp/project_policy_spec.rb.dump --method BasePolicy#abilities
+BasePolicy#abilities (/Users/lupine/dev/gitlab.com/gitlab-org/gitlab-development-kit/gitlab/app/policies/base_policy.rb:79)
+ samples: 0 self (0.0%) / 50 total (0.3%)
+ callers:
+ 25 ( 50.0%) BasePolicy.abilities
+ 25 ( 50.0%) BasePolicy#collect_rules
+ callees (50 total):
+ 25 ( 50.0%) ProjectPolicy#rules
+ 25 ( 50.0%) BasePolicy#collect_rules
+ code:
+ | 79 | def abilities
+ | 80 | return RuleSet.empty if @user && @user.blocked?
+ | 81 | return anonymous_abilities if @user.nil?
+ 50 (0.3%) | 82 | collect_rules { rules }
+ | 83 | end
+```
+
+Since the profile includes the work done by the test suite as well as the
+application code, these profiles can be used to investigate slow tests as well.
+However, for smaller runs (like this example), this means that the cost of
+setting up the test suite will tend to dominate.
+
+It's also possible to modify the application code in-place to output profiles
+whenever a particular code path is triggered without going through the test
+suite first. See the
+[StackProf documentation](https://github.com/tmm1/stackprof/blob/master/README.md)
+for details.
+
+## RSpec profiling
+
+GitLab's development environment also includes the
+[rspec_profiling](https://github.com/foraker/rspec_profiling) gem, which is used
+to collect data on spec execution times. This is useful for analyzing the
+performance of the test suite itself, or seeing how the performance of a spec
+may have changed over time.
+
+To activate profiling in your local environment, run the following:
+
+```
+$ export RSPEC_PROFILING=yes
+$ rake rspec_profiling:install
+```
+
+This creates an SQLite3 database in `tmp/rspec_profiling`, into which statistics
+are saved every time you run specs with the `RSPEC_PROFILING` environment
+variable set.
+
+Ad-hoc investigation of the collected results can be performed in an interactive
+shell:
+
+```
+$ rake rspec_profiling:console
+irb(main):001:0> results.count
+=> 231
+irb(main):002:0> results.last.attributes.keys
+=> ["id", "commit", "date", "file", "line_number", "description", "time", "status", "exception", "query_count", "query_time", "request_count", "request_time", "created_at", "updated_at"]
+irb(main):003:0> results.where(status: "passed").average(:time).to_s
+=> "0.211340155844156"
+```
+These results can also be placed into a PostgreSQL database by setting the
+`RSPEC_PROFILING_POSTGRES_URL` variable. This is used to profile the test suite
+when running in the CI environment.
+
## Importance of Changes
When working on performance improvements, it's important to always ask yourself
@@ -253,5 +400,5 @@ impact on runtime performance, and as such, using a constant instead of
referencing an object directly may even slow code down.
[#15607]: https://gitlab.com/gitlab-org/gitlab-ce/issues/15607
-[yorickpeterse]: https://gitlab.com/u/yorickpeterse
+[yorickpeterse]: https://gitlab.com/yorickpeterse
[anti-pattern]: https://en.wikipedia.org/wiki/Anti-pattern
diff --git a/doc/development/polling.md b/doc/development/polling.md
new file mode 100644
index 00000000000..3b34f985cd4
--- /dev/null
+++ b/doc/development/polling.md
@@ -0,0 +1,56 @@
+# Polling with ETag caching
+
+Polling for changes (repeatedly asking server if there are any new changes)
+introduces high load on a GitLab instance, because it usually requires
+executing at least a few SQL queries. This makes scaling large GitLab
+instances (like GitLab.com) very difficult so we do not allow adding new
+features that require polling and hit the database.
+
+Instead you should use polling mechanism with ETag caching in Redis.
+
+## How to use it
+
+1. Add the path of the endpoint which you want to poll to
+ `Gitlab::EtagCaching::Middleware`.
+1. Implement cache invalidation for the path of your endpoint using
+ `Gitlab::EtagCaching::Store`. Whenever a resource changes you
+ have to invalidate the ETag for the path that depends on this
+ resource.
+1. Check that the mechanism works:
+ - requests should return status code 304
+ - there should be no SQL queries logged in `log/development.log`
+
+## How it works
+
+Cache Miss:
+
+![Cache miss](img/cache-miss.svg)
+
+Cache Hit:
+
+![Cache hit](img/cache-hit.svg)
+
+1. Whenever a resource changes we generate a random value and store it in
+ Redis.
+1. When a client makes a request we set the `ETag` response header to the value
+ from Redis.
+1. The client caches the response (client-side caching) and sends the ETag as
+ the `If-None-Match` header with every subsequent request for the same
+ resource.
+1. If the `If-None-Match` header matches the current value in Redis we know
+ that the resource did not change so we can send 304 response immediately,
+ without querying the database at all. The client's browser will use the
+ cached response.
+1. If the `If-None-Match` header does not match the current value in Redis
+ we have to generate a new response, because the resource changed.
+
+Do not use query parameters (for example `?scope=all`) for endpoints where you
+want to enable ETag caching. The middleware takes into account only the request
+path and ignores query parameters. All parameters should be included in the
+request path. By doing this we avoid query parameter ordering problems and make
+route matching easier.
+
+For more information see:
+- [`Poll-Interval` header](fe_guide/performance.md#realtime-components)
+- [RFC 7232](https://tools.ietf.org/html/rfc7232)
+- [ETag proposal](https://gitlab.com/gitlab-org/gitlab-ce/issues/26926)
diff --git a/doc/development/polymorphic_associations.md b/doc/development/polymorphic_associations.md
new file mode 100644
index 00000000000..d63b9fb115f
--- /dev/null
+++ b/doc/development/polymorphic_associations.md
@@ -0,0 +1,146 @@
+# Polymorphic Associations
+
+**Summary:** always use separate tables instead of polymorphic associations.
+
+Rails makes it possible to define so called "polymorphic associations". This
+usually works by adding two columns to a table: a target type column, and a
+target id. For example, at the time of writing we have such a setup for
+`members` with the following columns:
+
+* `source_type`: a string defining the model to use, can be either `Project` or
+ `Namespace`.
+* `source_id`: the ID of the row to retrieve based on `source_type`. For
+ example, when `source_type` is `Project` then `source_id` will contain a
+ project ID.
+
+While such a setup may appear to be useful, it comes with many drawbacks; enough
+that you should avoid this at all costs.
+
+## Space Wasted
+
+Because this setup relies on string values to determine the model to use it will
+end up wasting a lot of space. For example, for `Project` and `Namespace` the
+maximum size is 9 bytes, plus 1 extra byte for every string when using
+PostgreSQL. While this may only be 10 bytes per row, given enough tables and
+rows using such a setup we can end up wasting quite a bit of disk space and
+memory (for any indexes).
+
+## Indexes
+
+Because our associations are broken up into two columns this may result in
+requiring composite indexes for queries to be performed efficiently. While
+composite indexes are not wrong at all, they can be tricky to set up as the
+ordering of columns in these indexes is important to ensure optimal performance.
+
+## Consistency
+
+One really big problem with polymorphic associations is being unable to enforce
+data consistency on the database level using foreign keys. For consistency to be
+enforced on the database level one would have to write their own foreign key
+logic to support polymorphic associations.
+
+Enforcing consistency on the database level is absolutely crucial for
+maintaining a healthy environment, and thus is another reason to avoid
+polymorphic associations.
+
+## Query Overhead
+
+When using polymorphic associations you always need to filter using both
+columns. For example, you may end up writing a query like this:
+
+```sql
+SELECT *
+FROM members
+WHERE source_type = 'Project'
+AND source_id = 13083;
+```
+
+Here PostgreSQL can perform the query quite efficiently if both columns are
+indexed, but as the query gets more complex it may not be able to use these
+indexes efficiently.
+
+## Mixed Responsibilities
+
+Similar to functions and classes a table should have a single responsibility:
+storing data with a certain set of pre-defined columns. When using polymorphic
+associations you are instead storing different types of data (possibly with
+different columns set) in the same table.
+
+## The Solution
+
+Fortunately there is a very simple solution to these problems: simply use a
+separate table for every type you would otherwise store in the same table. Using
+a separate table allows you to use everything a database may provide to ensure
+consistency and query data efficiently, without any additional application logic
+being necessary.
+
+Let's say you have a `members` table storing both approved and pending members,
+for both projects and groups, and the pending state is determined by the column
+`requested_at` being set or not. Schema wise such a setup can lead to various
+columns only being set for certain rows, wasting space. It's also possible that
+certain indexes will only be set for certain rows, again wasting space. Finally,
+querying such a table requires less than ideal queries. For example:
+
+```sql
+SELECT *
+FROM members
+WHERE requested_at IS NULL
+AND source_type = 'GroupMember'
+AND source_id = 4
+```
+
+Instead such a table should be broken up into separate tables. For example, you
+may end up with 4 tables in this case:
+
+* project_members
+* group_members
+* pending_project_members
+* pending_group_members
+
+This makes querying data trivial. For example, to get the members of a group
+you'd run:
+
+```sql
+SELECT *
+FROM group_members
+WHERE group_id = 4
+```
+
+To get all the pending members of a group in turn you'd run:
+
+```sql
+SELECT *
+FROM pending_group_members
+WHERE group_id = 4
+```
+
+If you want to get both you can use a UNION, though you need to be explicit
+about what columns you want to SELECT as otherwise the result set will use the
+columns of the first query. For example:
+
+```sql
+SELECT id, 'Group' AS target_type, group_id AS target_id
+FROM group_members
+
+UNION ALL
+
+SELECT id, 'Project' AS target_type, project_id AS target_id
+FROM project_members
+```
+
+The above example is perhaps a bit silly, but it shows that there's nothing
+stopping you from merging the data together and presenting it on the same page.
+Selecting columns explicitly can also speed up queries as the database has to do
+less work to get the data (compared to selecting all columns, even ones you're
+not using).
+
+Our schema also becomes easier. No longer do we need to both store and index the
+`source_type` column, we can define foreign keys easily, and we don't need to
+filter rows using the `IS NULL` condition.
+
+To summarize: using separate tables allows us to use foreign keys effectively,
+create indexes only where necessary, conserve space, query data more
+efficiently, and scale these tables more easily (e.g. by storing them on
+separate disks). A nice side effect of this is that code can also become easier
+as you won't end up with a single model having to handle different kinds of
+data.
diff --git a/doc/development/post_deployment_migrations.md b/doc/development/post_deployment_migrations.md
new file mode 100644
index 00000000000..cfc91539bee
--- /dev/null
+++ b/doc/development/post_deployment_migrations.md
@@ -0,0 +1,75 @@
+# Post Deployment Migrations
+
+Post deployment migrations are regular Rails migrations that can optionally be
+executed after a deployment. By default these migrations are executed alongside
+the other migrations. To skip these migrations you will have to set the
+environment variable `SKIP_POST_DEPLOYMENT_MIGRATIONS` to a non-empty value
+when running `rake db:migrate`.
+
+For example, this would run all migrations including any post deployment
+migrations:
+
+```bash
+bundle exec rake db:migrate
+```
+
+This however will skip post deployment migrations:
+
+```bash
+SKIP_POST_DEPLOYMENT_MIGRATIONS=true bundle exec rake db:migrate
+```
+
+## Deployment Integration
+
+Say you're using Chef for deploying new versions of GitLab and you'd like to run
+post deployment migrations after deploying a new version. Let's assume you
+normally use the command `chef-client` to do so. To make use of this feature
+you'd have to run this command as follows:
+
+```bash
+SKIP_POST_DEPLOYMENT_MIGRATIONS=true sudo chef-client
+```
+
+Once all servers have been updated you can run `chef-client` again on a single
+server _without_ the environment variable.
+
+The process is similar for other deployment techniques: first you would deploy
+with the environment variable set, then you'll essentially re-deploy a single
+server but with the variable _unset_.
+
+## Creating Migrations
+
+To create a post deployment migration you can use the following Rails generator:
+
+```bash
+bundle exec rails g post_deployment_migration migration_name_here
+```
+
+This will generate the migration file in `db/post_migrate`. These migrations
+behave exactly like regular Rails migrations.
+
+## Use Cases
+
+Post deployment migrations can be used to perform migrations that mutate state
+that an existing version of GitLab depends on. For example, say you want to
+remove a column from a table. This requires downtime as a GitLab instance
+depends on this column being present while it's running. Normally you'd follow
+these steps in such a case:
+
+1. Stop the GitLab instance
+2. Run the migration removing the column
+3. Start the GitLab instance again
+
+Using post deployment migrations we can instead follow these steps:
+
+1. Deploy a new version of GitLab while ignoring post deployment migrations
+2. Re-run `rake db:migrate` but without the environment variable set
+
+Here we don't need any downtime as the migration takes place _after_ a new
+version (which doesn't depend on the column anymore) has been deployed.
+
+Some other examples where these migrations are useful:
+
+* Cleaning up data generated due to a bug in GitLab
+* Removing tables
+* Migrating jobs from one Sidekiq queue to another
diff --git a/doc/development/profiling.md b/doc/development/profiling.md
index e244ad4e881..933033a09e0 100644
--- a/doc/development/profiling.md
+++ b/doc/development/profiling.md
@@ -25,3 +25,5 @@ starting GitLab. For example:
Bullet will log query problems to both the Rails log as well as the Chrome
console.
+
+As a follow up to finding `N+1` queries with Bullet, consider writing a [QueryRecoder test](query_recorder.md) to prevent a regression.
diff --git a/doc/development/query_recorder.md b/doc/development/query_recorder.md
new file mode 100644
index 00000000000..e0127aaed4c
--- /dev/null
+++ b/doc/development/query_recorder.md
@@ -0,0 +1,29 @@
+# QueryRecorder
+
+QueryRecorder is a tool for detecting the [N+1 queries problem](http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations) from tests.
+
+> Implemented in [spec/support/query_recorder.rb](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/spec/support/query_recorder.rb) via [9c623e3e](https://gitlab.com/gitlab-org/gitlab-ce/commit/9c623e3e5d7434f2e30f7c389d13e5af4ede770a)
+
+As a rule, merge requests [should not increase query counts](merge_request_performance_guidelines.md#query-counts). If you find yourself adding something like `.includes(:author, :assignee)` to avoid having `N+1` queries, consider using QueryRecorder to enforce this with a test. Without this, a new feature which causes an additional model to be accessed will silently reintroduce the problem.
+
+## How it works
+
+This style of test works by counting the number of SQL queries executed by ActiveRecord. First a control count is taken, then you add new records to the database and rerun the count. If the number of queries has significantly increased then an `N+1` queries problem exists.
+
+```ruby
+it "avoids N+1 database queries" do
+ control_count = ActiveRecord::QueryRecorder.new { visit_some_page }.count
+ create_list(:issue, 5)
+ expect { visit_some_page }.not_to exceed_query_limit(control_count)
+end
+```
+
+As an example you might create 5 issues in between counts, which would cause the query count to increase by 5 if an N+1 problem exists.
+
+> **Note:** In some cases the query count might change slightly between runs for unrelated reasons. In this case you might need to test `exceed_query_limit(control_count + acceptable_change)`, but this should be avoided if possible.
+
+## See also
+
+- [Bullet](profiling.md#Bullet) For finding `N+1` query problems
+- [Performance guidelines](performance.md)
+- [Merge request performance guidelines](merge_request_performance_guidelines.md#query-counts) \ No newline at end of file
diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md
index a7175f3f87e..fdaaa65fa28 100644
--- a/doc/development/rake_tasks.md
+++ b/doc/development/rake_tasks.md
@@ -17,39 +17,55 @@ Note: `db:setup` calls `db:seed` but this does nothing.
In order to run the test you can use the following commands:
- `rake spinach` to run the spinach suite
- `rake spec` to run the rspec suite
-- `rake teaspoon` to run the teaspoon test suite
+- `rake karma` to run the karma test suite
- `rake gitlab:test` to run all the tests
-Note: Both `rake spinach` and `rake spec` takes significant time to pass.
+Note: Both `rake spinach` and `rake spec` takes significant time to pass.
Instead of running full test suite locally you can save a lot of time by running
-a single test or directory related to your changes. After you submit merge request
-CI will run full test suite for you. Green CI status in the merge request means
-full test suite is passed.
+a single test or directory related to your changes. After you submit merge request
+CI will run full test suite for you. Green CI status in the merge request means
+full test suite is passed.
Note: You can't run `rspec .` since this will try to run all the `_spec.rb`
files it can find, also the ones in `/tmp`
To run a single test file you can use:
-- `bundle exec rspec spec/controllers/commit_controller_spec.rb` for a rspec test
-- `bundle exec spinach features/project/issues/milestones.feature` for a spinach test
+- `bin/rspec spec/controllers/commit_controller_spec.rb` for a rspec test
+- `bin/spinach features/project/issues/milestones.feature` for a spinach test
To run several tests inside one directory:
-- `bundle exec rspec spec/requests/api/` for the rspec tests if you want to test API only
-- `bundle exec spinach features/profile/` for the spinach tests if you want to test only profile pages
+- `bin/rspec spec/requests/api/` for the rspec tests if you want to test API only
+- `bin/spinach features/profile/` for the spinach tests if you want to test only profile pages
-If you want to use [Spring](https://github.com/rails/spring) set
-`ENABLE_SPRING=1` in your environment.
+### Speed-up tests, rake tasks, and migrations
-## Generate searchable docs for source code
+[Spring](https://github.com/rails/spring) is a Rails application preloader. It
+speeds up development by keeping your application running in the background so
+you don't need to boot it every time you run a test, rake task or migration.
-You can find results under the `doc/code` directory.
+If you want to use it, you'll need to export the `ENABLE_SPRING` environment
+variable to `1`:
```
-bundle exec rake gitlab:generate_docs
+export ENABLE_SPRING=1
```
+## Compile Frontend Assets
+
+You shouldn't ever need to compile frontend assets manually in development, but
+if you ever need to test how the assets get compiled in a production
+environment you can do so with the following command:
+
+```
+RAILS_ENV=production NODE_ENV=production bundle exec rake gitlab:assets:compile
+```
+
+This will compile and minify all JavaScript and CSS assets and copy them along
+with all other frontend assets (images, fonts, etc) into `/public/assets` where
+they can be easily inspected.
+
## Generate API documentation for project services (e.g. Slack)
```
diff --git a/doc/development/serializing_data.md b/doc/development/serializing_data.md
new file mode 100644
index 00000000000..2b56f48bc44
--- /dev/null
+++ b/doc/development/serializing_data.md
@@ -0,0 +1,84 @@
+# Serializing Data
+
+**Summary:** don't store serialized data in the database, use separate columns
+and/or tables instead.
+
+Rails makes it possible to store serialized data in JSON, YAML or other formats.
+Such a field can be defined as follows:
+
+```ruby
+class Issue < ActiveRecord::Model
+ serialize :custom_fields
+end
+```
+
+While it may be tempting to store serialized data in the database there are many
+problems with this. This document will outline these problems and provide an
+alternative.
+
+## Serialized Data Is Less Powerful
+
+When using a relational database you have the ability to query individual
+fields, change the schema, index data and so forth. When you use serialized data
+all of that becomes either very difficult or downright impossible. While
+PostgreSQL does offer the ability to query JSON fields it is mostly meant for
+very specialized use cases, and not for more general use. If you use YAML in
+turn there's no way to query the data at all.
+
+## Waste Of Space
+
+Storing serialized data such as JSON or YAML will end up wasting a lot of space.
+This is because these formats often include additional characters (e.g. double
+quotes or newlines) besides the data that you are storing.
+
+## Difficult To Manage
+
+There comes a time where you will need to add a new field to the serialized
+data, or change an existing one. Using serialized data this becomes difficult
+and very time consuming as the only way of doing so is to re-write all the
+stored values. To do so you would have to:
+
+1. Retrieve the data
+1. Parse it into a Ruby structure
+1. Mutate it
+1. Serialize it back to a String
+1. Store it in the database
+
+On the other hand, if one were to use regular columns adding a column would be
+as easy as this:
+
+```sql
+ALTER TABLE table_name ADD COLUMN column_name type;
+```
+
+Such a query would take very little to no time and would immediately apply to
+all rows, without having to re-write large JSON or YAML structures.
+
+Finally, there comes a time when the JSON or YAML structure is no longer
+sufficient and you need to migrate away from it. When storing only a few rows
+this may not be a problem, but when storing millions of rows such a migration
+can easily take hours or even days to complete.
+
+## Relational Databases Are Not Document Stores
+
+When storing data as JSON or YAML you're essentially using your database as if
+it were a document store (e.g. MongoDB), except you're not using any of the
+powerful features provided by a typical RDBMS _nor_ are you using any of the
+features provided by a typical document store (e.g. the ability to index fields
+of documents with variable fields). In other words, it's a waste.
+
+## Consistent Fields
+
+One argument sometimes made in favour of serialized data is having to store
+widely varying fields and values. Sometimes this is truly the case, and then
+perhaps it might make sense to use serialized data. However, in 99% of the cases
+the fields and types stored tend to be the same for every row. Even if there is
+a slight difference you can still use separate columns and just not set the ones
+you don't need.
+
+## The Solution
+
+The solution is very simple: just use separate columns and/or separate tables.
+This will allow you to use all the features provided by your database, it will
+make it easier to manage and migrate the data, you'll conserve space, you can
+index the data efficiently and so forth.
diff --git a/doc/development/shell_commands.md b/doc/development/shell_commands.md
index 65cdd74bdb6..73893f9dd46 100644
--- a/doc/development/shell_commands.md
+++ b/doc/development/shell_commands.md
@@ -129,7 +129,7 @@ Various methods for opening and reading files in Ruby can be used to read the
standard output of a process instead of a file. The following two commands do
roughly the same:
-```
+```ruby
`touch /tmp/pawned-by-backticks`
File.read('|touch /tmp/pawned-by-file-read')
```
@@ -142,7 +142,7 @@ attacker cannot control the start of the filename string you are opening. For
instance, the following is sufficient to protect against accidentally starting
a shell command with `|`:
-```
+```ruby
# we assume repo_path is not controlled by the attacker (user)
path = File.join(repo_path, user_input)
# path cannot start with '|' now.
@@ -160,7 +160,7 @@ Path traversal is a security where the program (GitLab) tries to restrict user
access to a certain directory on disk, but the user manages to open a file
outside that directory by taking advantage of the `../` path notation.
-```
+```ruby
# Suppose the user gave us a path and they are trying to trick us
user_input = '../other-repo.git/other-file'
@@ -177,7 +177,7 @@ File.open(full_path) do # Oops!
A good way to protect against this is to compare the full path with its
'absolute path' according to Ruby's `File.absolute_path`.
-```
+```ruby
full_path = File.join(repo_path, user_input)
if full_path != File.absolute_path(full_path)
raise "Invalid path: #{full_path.inspect}"
diff --git a/doc/development/sidekiq_debugging.md b/doc/development/sidekiq_debugging.md
index cea11e5f126..d6d770e27c1 100644
--- a/doc/development/sidekiq_debugging.md
+++ b/doc/development/sidekiq_debugging.md
@@ -3,12 +3,15 @@
## Log arguments to Sidekiq jobs
If you want to see what arguments are being passed to Sidekiq jobs you can set
-the SIDEKIQ_LOG_ARGUMENTS environment variable.
+the `SIDEKIQ_LOG_ARGUMENTS` [environment variable]
+(https://docs.gitlab.com/omnibus/settings/environment-variables.html) to `1` (true).
+
+Example:
```
-SIDEKIQ_LOG_ARGUMENTS=1 bundle exec foreman start
+gitlab_rails['env'] = {"SIDEKIQ_LOG_ARGUMENTS" => "1"}
```
-It is not recommend to enable this setting in production because some Sidekiq
-jobs (such as sending a password reset email) take secret arguments (for
-example the password reset token).
+Please note: It is not recommend to enable this setting in production because some
+Sidekiq jobs (such as sending a password reset email) take secret arguments (for
+example the password reset token). \ No newline at end of file
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
new file mode 100644
index 00000000000..e3a20f29a09
--- /dev/null
+++ b/doc/development/sidekiq_style_guide.md
@@ -0,0 +1,38 @@
+# Sidekiq Style Guide
+
+This document outlines various guidelines that should be followed when adding or
+modifying Sidekiq workers.
+
+## Default Queue
+
+Use of the "default" queue is not allowed. Every worker should use a queue that
+matches the worker's purpose the closest. For example, workers that are to be
+executed periodically should use the "cronjob" queue.
+
+A list of all available queues can be found in `config/sidekiq_queues.yml`.
+
+## Dedicated Queues
+
+Most workers should use their own queue. To ease this process a worker can
+include the `DedicatedSidekiqQueue` concern as follows:
+
+```ruby
+class ProcessSomethingWorker
+ include Sidekiq::Worker
+ include DedicatedSidekiqQueue
+end
+```
+
+This will set the queue name based on the class' name, minus the `Worker`
+suffix. In the above example this would lead to the queue being
+`process_something`.
+
+In some cases multiple workers do use the same queue. For example, the various
+workers for updating CI pipelines all use the `pipeline` queue. Adding workers
+to existing queues should be done with care, as adding more workers can lead to
+slow jobs blocking work (even for different jobs) on the shared queue.
+
+## Tests
+
+Each Sidekiq worker must be tested using RSpec, just like any other class. These
+tests should be placed in `spec/workers`.
diff --git a/doc/development/single_table_inheritance.md b/doc/development/single_table_inheritance.md
new file mode 100644
index 00000000000..27c3c4f3199
--- /dev/null
+++ b/doc/development/single_table_inheritance.md
@@ -0,0 +1,18 @@
+# Single Table Inheritance
+
+**Summary:** don't use Single Table Inheritance (STI), use separate tables
+instead.
+
+Rails makes it possible to have multiple models stored in the same table and map
+these rows to the correct models using a `type` column. This can be used to for
+example store two different types of SSH keys in the same table.
+
+While tempting to use one should avoid this at all costs for the same reasons as
+outlined in the document ["Polymorphic Associations"](polymorphic_associations.md).
+
+## Solution
+
+The solution is very simple: just use a separate table for every type you'd
+otherwise store in the same table. For example, instead of having a `keys` table
+with `type` set to either `Key` or `DeployKey` you'd have two separate tables:
+`keys` and `deploy_keys`.
diff --git a/doc/development/testing.md b/doc/development/testing.md
index 513457d203a..cf3ea2ccfc2 100644
--- a/doc/development/testing.md
+++ b/doc/development/testing.md
@@ -9,66 +9,201 @@ this guide defines a rule that contradicts the thoughtbot guide, this guide
takes precedence. Some guidelines may be repeated verbatim to stress their
importance.
-## Factories
+## Definitions
+
+### Unit tests
+
+Formal definition: https://en.wikipedia.org/wiki/Unit_testing
+
+These kind of tests ensure that a single unit of code (a method) works as
+expected (given an input, it has a predictable output). These tests should be
+isolated as much as possible. For example, model methods that don't do anything
+with the database shouldn't need a DB record. Classes that don't need database
+records should use stubs/doubles as much as possible.
+
+| Code path | Tests path | Testing engine | Notes |
+| --------- | ---------- | -------------- | ----- |
+| `app/finders/` | `spec/finders/` | RSpec | |
+| `app/helpers/` | `spec/helpers/` | RSpec | |
+| `app/db/{post_,}migrate/` | `spec/migrations/` | RSpec | More details at [`spec/migrations/README.md`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/spec/migrations/README.md). |
+| `app/policies/` | `spec/policies/` | RSpec | |
+| `app/presenters/` | `spec/presenters/` | RSpec | |
+| `app/routing/` | `spec/routing/` | RSpec | |
+| `app/serializers/` | `spec/serializers/` | RSpec | |
+| `app/services/` | `spec/services/` | RSpec | |
+| `app/tasks/` | `spec/tasks/` | RSpec | |
+| `app/uploaders/` | `spec/uploaders/` | RSpec | |
+| `app/views/` | `spec/views/` | RSpec | |
+| `app/workers/` | `spec/workers/` | RSpec | |
+| `app/assets/javascripts/` | `spec/javascripts/` | Karma | More details in the [JavaScript](#javascript) section. |
+
+### Integration tests
+
+Formal definition: https://en.wikipedia.org/wiki/Integration_testing
+
+These kind of tests ensure that individual parts of the application work well together, without the overhead of the actual app environment (i.e. the browser). These tests should assert at the request/response level: status code, headers, body. They're useful to test permissions, redirections, what view is rendered etc.
+
+| Code path | Tests path | Testing engine | Notes |
+| --------- | ---------- | -------------- | ----- |
+| `app/controllers/` | `spec/controllers/` | RSpec | |
+| `app/mailers/` | `spec/mailers/` | RSpec | |
+| `lib/api/` | `spec/requests/api/` | RSpec | |
+| `lib/ci/api/` | `spec/requests/ci/api/` | RSpec | |
+| `app/assets/javascripts/` | `spec/javascripts/` | Karma | More details in the [JavaScript](#javascript) section. |
+
+#### About controller tests
+
+In an ideal world, controllers should be thin. However, when this is not the
+case, it's acceptable to write a system/feature test without JavaScript instead
+of a controller test. The reason is that testing a fat controller usually
+involves a lot of stubbing, things like:
+
+```ruby
+controller.instance_variable_set(:@user, user)
+```
+
+and use methods which are deprecated in Rails 5 ([#23768]).
+
+[#23768]: https://gitlab.com/gitlab-org/gitlab-ce/issues/23768
+
+#### About Karma
+
+As you may have noticed, Karma is both in the Unit tests and the Integration
+tests category. That's because Karma is a tool that provides an environment to
+run JavaScript tests, so you can either run unit tests (e.g. test a single
+JavaScript method), or integration tests (e.g. test a component that is composed
+of multiple components).
+
+### System tests or Feature tests
+
+Formal definition: https://en.wikipedia.org/wiki/System_testing.
+
+These kind of tests ensure the application works as expected from a user point
+of view (aka black-box testing). These tests should test a happy path for a
+given page or set of pages, and a test case should be added for any regression
+that couldn't have been caught at lower levels with better tests (i.e. if a
+regression is found, regression tests should be added at the lowest-level
+possible).
+
+| Tests path | Testing engine | Notes |
+| ---------- | -------------- | ----- |
+| `spec/features/` | [Capybara] + [RSpec] | If your spec has the `:js` metadata, the browser driver will be [Poltergeist], otherwise it's using [RackTest]. |
+| `features/` | Spinach | Spinach tests are deprecated, [you shouldn't add new Spinach tests](#spinach-feature-tests). |
+
+[Capybara]: https://github.com/teamcapybara/capybara
+[RSpec]: https://github.com/rspec/rspec-rails#feature-specs
+[Poltergeist]: https://github.com/teamcapybara/capybara#poltergeist
+[RackTest]: https://github.com/teamcapybara/capybara#racktest
+
+#### Best practices
+
+- Create only the necessary records in the database
+- Test a happy path and a less happy path but that's it
+- Every other possible path should be tested with Unit or Integration tests
+- Test what's displayed on the page, not the internals of ActiveRecord models.
+ For instance, if you want to verify that a record was created, add
+ expectations that its attributes are displayed on the page, not that
+ `Model.count` increased by one.
+- It's ok to look for DOM elements but don't abuse it since it makes the tests
+ more brittle
+
+If we're confident that the low-level components work well (and we should be if
+we have enough Unit & Integration tests), we shouldn't need to duplicate their
+thorough testing at the System test level.
+
+It's very easy to add tests, but a lot harder to remove or improve tests, so one
+should take care of not introducing too many (slow and duplicated) specs.
+
+The reasons why we should follow these best practices are as follows:
+
+- System tests are slow to run since they spin up the entire application stack
+ in a headless browser, and even slower when they integrate a JS driver
+- When system tests run with a JavaScript driver, the tests are run in a
+ different thread than the application. This means it does not share a
+ database connection and your test will have to commit the transactions in
+ order for the running application to see the data (and vice-versa). In that
+ case we need to truncate the database after each spec instead of simply
+ rolling back a transaction (the faster strategy that's in use for other kind
+ of tests). This is slower than transactions, however, so we want to use
+ truncation only when necessary.
+
+### Black-box tests or End-to-end tests
+
+GitLab consists of [multiple pieces] such as [GitLab Shell], [GitLab Workhorse],
+[Gitaly], [GitLab Pages], [GitLab Runner], and GitLab Rails. All theses pieces
+are configured and packaged by [GitLab Omnibus].
+
+[GitLab QA] is a tool that allows to test that all these pieces integrate well
+together by building a Docker image for a given version of GitLab Rails and
+running feature tests (i.e. using Capybara) against it.
-GitLab uses [factory_girl] as a test fixture replacement.
-
-- Factory definitions live in `spec/factories/`, named using the pluralization
- of their corresponding model (`User` factories are defined in `users.rb`).
-- There should be only one top-level factory definition per file.
-- FactoryGirl methods are mixed in to all RSpec groups. This means you can (and
- should) call `create(...)` instead of `FactoryGirl.create(...)`.
-- Make use of [traits] to clean up definitions and usages.
-- When defining a factory, don't define attributes that are not required for the
- resulting record to pass validation.
-- When instantiating from a factory, don't supply attributes that aren't
- required by the test.
-- Factories don't have to be limited to `ActiveRecord` objects.
- [See example](https://gitlab.com/gitlab-org/gitlab-ce/commit/0b8cefd3b2385a21cfed779bd659978c0402766d).
-
-[factory_girl]: https://github.com/thoughtbot/factory_girl
-[traits]: http://www.rubydoc.info/gems/factory_girl/file/GETTING_STARTED.md#Traits
-
-## JavaScript
-
-GitLab uses [Teaspoon] to run its [Jasmine] JavaScript specs. They can be run on
-the command line via `bundle exec teaspoon`, or via a web browser at
-`http://localhost:3000/teaspoon` when the Rails server is running.
-
-- JavaScript tests live in `spec/javascripts/`, matching the folder structure of
- `app/assets/javascripts/`: `app/assets/javascripts/behaviors/autosize.js.coffee` has a corresponding
- `spec/javascripts/behaviors/autosize_spec.js.coffee` file.
-- Haml fixtures required for JavaScript tests live in
- `spec/javascripts/fixtures`. They should contain the bare minimum amount of
- markup necessary for the test.
-
- > **Warning:** Keep in mind that a Rails view may change and
- invalidate your test, but everything will still pass because your fixture
- doesn't reflect the latest view.
-
-- Keep in mind that in a CI environment, these tests are run in a headless
- browser and you will not have access to certain APIs, such as
- [`Notification`](https://developer.mozilla.org/en-US/docs/Web/API/notification),
- which will have to be stubbed.
-
-[Teaspoon]: https://github.com/modeset/teaspoon
-[Jasmine]: https://github.com/jasmine/jasmine
+The actual test scenarios and steps are [part of GitLab Rails] so that they're
+always in-sync with the codebase.
+
+[multiple pieces]: ./architecture.md#components
+[GitLab Shell]: https://gitlab.com/gitlab-org/gitlab-shell
+[GitLab Workhorse]: https://gitlab.com/gitlab-org/gitlab-workhorse
+[Gitaly]: https://gitlab.com/gitlab-org/gitaly
+[GitLab Pages]: https://gitlab.com/gitlab-org/gitlab-pages
+[GitLab Runner]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner
+[GitLab Omnibus]: https://gitlab.com/gitlab-org/omnibus-gitlab
+[GitLab QA]: https://gitlab.com/gitlab-org/gitlab-qa
+[part of GitLab Rails]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa
+
+## How to test at the correct level?
+
+As many things in life, deciding what to test at each level of testing is a
+trade-off:
+
+- Unit tests are usually cheap, and you should consider them like the basement
+ of your house: you need them to be confident that your code is behaving
+ correctly. However if you run only unit tests without integration / system tests, you might [miss] the [big] [picture]!
+- Integration tests are a bit more expensive, but don't abuse them. A feature test
+ is often better than an integration test that is stubbing a lot of internals.
+- System tests are expensive (compared to unit tests), even more if they require
+ a JavaScript driver. Make sure to follow the guidelines in the [Speed](#test-speed)
+ section.
+
+Another way to see it is to think about the "cost of tests", this is well
+explained [in this article][tests-cost] and the basic idea is that the cost of a
+test includes:
+
+- The time it takes to write the test
+- The time it takes to run the test every time the suite runs
+- The time it takes to understand the test
+- The time it takes to fix the test if it breaks and the underlying code is OK
+- Maybe, the time it takes to change the code to make the code testable.
+
+[miss]: https://twitter.com/ThePracticalDev/status/850748070698651649
+[big]: https://twitter.com/timbray/status/822470746773409794
+[picture]: https://twitter.com/withzombies/status/829716565834752000
+[tests-cost]: https://medium.com/table-xi/high-cost-tests-and-high-value-tests-a86e27a54df#.2ulyh3a4e
+
+## Frontend testing
+
+Please consult the [dedicated "Frontend testing" guide](./fe_guide/testing.md).
## RSpec
### General Guidelines
- Use a single, top-level `describe ClassName` block.
-- Use `described_class` instead of repeating the class name being described.
+- Use `described_class` instead of repeating the class name being described
+ (_this is enforced by RuboCop_).
- Use `.method` to describe class methods and `#method` to describe instance
methods.
- Use `context` to test branching logic.
+- Use multi-line `do...end` blocks for `before` and `after`, even when it would
+ fit on a single line.
- Don't `describe` symbols (see [Gotchas](gotchas.md#dont-describe-symbols)).
+- Don't assert against the absolute value of a sequence-generated attribute (see [Gotchas](gotchas.md#dont-assert-against-the-absolute-value-of-a-sequence-generated-attribute)).
- Don't supply the `:each` argument to hooks since it's the default.
-- Prefer `not_to` to `to_not` (_this is enforced by Rubocop_).
+- Prefer `not_to` to `to_not` (_this is enforced by RuboCop_).
- Try to match the ordering of tests to the ordering within the class.
- Try to follow the [Four-Phase Test][four-phase-test] pattern, using newlines
to separate phases.
+- Try to use `Gitlab.config.gitlab.host` rather than hard coding `'localhost'`
+- On `before` and `after` hooks, prefer it scoped to `:context` over `:all`
[four-phase-test]: https://robots.thoughtbot.com/four-phase-test
@@ -92,11 +227,199 @@ so we need to set some guidelines for their use going forward:
[lets-not]: https://robots.thoughtbot.com/lets-not
-### Test speed
+#### `set` variables
+
+In some cases there is no need to recreate the same object for tests again for
+each example. For example, a project is needed to test issues on the same
+project, one project will do for the entire file. This can be achieved by using
+`set` in the same way you would use `let`.
+
+`rspec-set` only works on ActiveRecord objects, and before new examples it
+reloads or recreates the model, _only_ if needed. That is, when you changed
+properties or destroyed the object.
+
+There is one gotcha; you can't reference a model defined in a `let` block in a
+`set` block.
+
+### Time-sensitive tests
+
+[Timecop](https://github.com/travisjeffery/timecop) is available in our
+Ruby-based tests for verifying things that are time-sensitive. Any test that
+exercises or verifies something time-sensitive should make use of Timecop to
+prevent transient test failures.
+
+Example:
+
+```ruby
+it 'is overdue' do
+ issue = build(:issue, due_date: Date.tomorrow)
+
+ Timecop.freeze(3.days.from_now) do
+ expect(issue).to be_overdue
+ end
+end
+```
+
+### System / Feature tests
+
+- Feature specs should be named `ROLE_ACTION_spec.rb`, such as
+ `user_changes_password_spec.rb`.
+- Use only one `feature` block per feature spec file.
+- Use scenario titles that describe the success and failure paths.
+- Avoid scenario titles that add no information, such as "successfully".
+- Avoid scenario titles that repeat the feature title.
+
+### Matchers
+
+Custom matchers should be created to clarify the intent and/or hide the
+complexity of RSpec expectations.They should be placed under
+`spec/support/matchers/`. Matchers can be placed in subfolder if they apply to
+a certain type of specs only (e.g. features, requests etc.) but shouldn't be if
+they apply to multiple type of specs.
+
+### Shared contexts
+
+All shared contexts should be be placed under `spec/support/shared_contexts/`.
+Shared contexts can be placed in subfolder if they apply to a certain type of
+specs only (e.g. features, requests etc.) but shouldn't be if they apply to
+multiple type of specs.
+
+Each file should include only one context and have a descriptive name, e.g.
+`spec/support/shared_contexts/controllers/githubish_import_controller_shared_context.rb`.
+
+### Shared examples
+
+All shared examples should be be placed under `spec/support/shared_examples/`.
+Shared examples can be placed in subfolder if they apply to a certain type of
+specs only (e.g. features, requests etc.) but shouldn't be if they apply to
+multiple type of specs.
+
+Each file should include only one context and have a descriptive name, e.g.
+`spec/support/shared_examples/controllers/githubish_import_controller_shared_example.rb`.
+
+### Helpers
+
+Helpers are usually modules that provide some methods to hide the complexity of
+specific RSpec examples. You can define helpers in RSpec files if they're not
+intended to be shared with other specs. Otherwise, they should be be placed
+under `spec/support/helpers/`. Helpers can be placed in subfolder if they apply
+to a certain type of specs only (e.g. features, requests etc.) but shouldn't be
+if they apply to multiple type of specs.
+
+Helpers should follow the Rails naming / namespacing convention. For instance
+`spec/support/helpers/cycle_analytics_helpers.rb` should define:
+
+```ruby
+module Spec
+ module Support
+ module Helpers
+ module CycleAnalyticsHelpers
+ def create_commit_referencing_issue(issue, branch_name: random_git_name)
+ project.repository.add_branch(user, branch_name, 'master')
+ create_commit("Commit for ##{issue.iid}", issue.project, user, branch_name)
+ end
+ end
+ end
+ end
+end
+```
+
+Helpers should not change the RSpec config. For instance, the helpers module
+described above should not include:
+
+```ruby
+RSpec.configure do |config|
+ config.include Spec::Support::Helpers::CycleAnalyticsHelpers
+end
+```
-GitLab has a massive test suite that, without parallelization, can take more
-than an hour to run. It's important that we make an effort to write tests that
-are accurate and effective _as well as_ fast.
+### Factories
+
+GitLab uses [factory_girl] as a test fixture replacement.
+
+- Factory definitions live in `spec/factories/`, named using the pluralization
+ of their corresponding model (`User` factories are defined in `users.rb`).
+- There should be only one top-level factory definition per file.
+- FactoryGirl methods are mixed in to all RSpec groups. This means you can (and
+ should) call `create(...)` instead of `FactoryGirl.create(...)`.
+- Make use of [traits] to clean up definitions and usages.
+- When defining a factory, don't define attributes that are not required for the
+ resulting record to pass validation.
+- When instantiating from a factory, don't supply attributes that aren't
+ required by the test.
+- Factories don't have to be limited to `ActiveRecord` objects.
+ [See example](https://gitlab.com/gitlab-org/gitlab-ce/commit/0b8cefd3b2385a21cfed779bd659978c0402766d).
+
+[factory_girl]: https://github.com/thoughtbot/factory_girl
+[traits]: http://www.rubydoc.info/gems/factory_girl/file/GETTING_STARTED.md#Traits
+
+### Fixtures
+
+All fixtures should be be placed under `spec/fixtures/`.
+
+### Config
+
+RSpec config files are files that change the RSpec config (i.e.
+`RSpec.configure do |config|` blocks). They should be placed under
+`spec/support/config/`.
+
+Each file should be related to a specific domain, e.g.
+`spec/support/config/capybara.rb`, `spec/support/config/carrierwave.rb`, etc.
+
+Helpers can be included in the `spec/support/config/rspec.rb` file. If a
+helpers module applies only to a certain kind of specs, it should add modifiers
+to the `config.include` call. For instance if
+`spec/support/helpers/cycle_analytics_helpers.rb` applies to `:lib` and
+`type: :model` specs only, you would write the following:
+
+```ruby
+RSpec.configure do |config|
+ config.include Spec::Support::Helpers::CycleAnalyticsHelpers, :lib
+ config.include Spec::Support::Helpers::CycleAnalyticsHelpers, type: :model
+end
+```
+
+## Testing Rake Tasks
+
+To make testing Rake tasks a little easier, there is a helper that can be included
+in lieu of the standard Spec helper. Instead of `require 'spec_helper'`, use
+`require 'rake_helper'`. The helper includes `spec_helper` for you, and configures
+a few other things to make testing Rake tasks easier.
+
+At a minimum, requiring the Rake helper will redirect `stdout`, include the
+runtime task helpers, and include the `RakeHelpers` Spec support module.
+
+The `RakeHelpers` module exposes a `run_rake_task(<task>)` method to make
+executing tasks simple. See `spec/support/rake_helpers.rb` for all available
+methods.
+
+Example:
+
+```ruby
+require 'rake_helper'
+
+describe 'gitlab:shell rake tasks' do
+ before do
+ Rake.application.rake_require 'tasks/gitlab/shell'
+
+ stub_warn_user_is_not_gitlab
+ end
+
+ describe 'install task' do
+ it 'invokes create_hooks task' do
+ expect(Rake::Task['gitlab:shell:create_hooks']).to receive(:invoke)
+
+ run_rake_task('gitlab:shell:install')
+ end
+ end
+end
+```
+
+## Test speed
+
+GitLab has a massive test suite that, without [parallelization], can take hours
+to run. It's important that we make an effort to write tests that are accurate
+and effective _as well as_ fast.
Here are some things to keep in mind regarding test performance:
@@ -107,17 +430,55 @@ Here are some things to keep in mind regarding test performance:
- Use `create(:empty_project)` instead of `create(:project)` when you don't need
the underlying Git repository. Filesystem operations are slow!
- Don't mark a feature as requiring JavaScript (through `@javascript` in
- Spinach or `js: true` in RSpec) unless it's _actually_ required for the test
+ Spinach or `:js` in RSpec) unless it's _actually_ required for the test
to be valid. Headless browser testing is slow!
-### Features / Integration
+[parallelization]: #test-suite-parallelization-on-the-ci
-- Feature specs live in `spec/features/` and should be named
- `ROLE_ACTION_spec.rb`, such as `user_changes_password_spec.rb`.
-- Use only one `feature` block per feature spec file.
-- Use scenario titles that describe the success and failure paths.
-- Avoid scenario titles that add no information, such as "successfully."
-- Avoid scenario titles that repeat the feature title.
+### Test suite parallelization on the CI
+
+Our current CI parallelization setup is as follows:
+
+1. The `knapsack` job in the prepare stage that is supposed to ensure we have a
+ `knapsack/${CI_PROJECT_NAME}/rspec_report-master.json` file:
+ - The `knapsack/${CI_PROJECT_NAME}/rspec_report-master.json` file is fetched
+ from S3, if it's not here we initialize the file with `{}`.
+1. Each `rspec x y` job are run with `knapsack rspec` and should have an evenly
+ distributed share of tests:
+ - It works because the jobs have access to the
+ `knapsack/${CI_PROJECT_NAME}/rspec_report-master.json` since the "artifacts
+ from all previous stages are passed by default". [^1]
+ - the jobs set their own report path to
+ `KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json`.
+ - if knapsack is doing its job, test files that are run should be listed under
+ `Report specs`, not under `Leftover specs`.
+1. The `update-knapsack` job takes all the
+ `knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json`
+ files from the `rspec x y` jobs and merge them all together into a single
+ `knapsack/${CI_PROJECT_NAME}/rspec_report-master.json` file that is then
+ uploaded to S3.
+
+After that, the next pipeline will use the up-to-date
+`knapsack/${CI_PROJECT_NAME}/rspec_report-master.json` file. The same strategy
+is used for Spinach tests as well.
+
+### Monitoring
+
+The GitLab test suite is [monitored] for the `master` branch, and any branch
+that includes `rspec-profile` in their name.
+
+A [public dashboard] is available for everyone to see. Feel free to look at the
+slowest test files and try to improve them.
+
+[monitored]: ./performance.md#rspec-profiling
+[public dashboard]: https://redash.gitlab.com/public/dashboards/l1WhHXaxrCWM5Ai9D7YDqHKehq6OU3bx5gssaiWe?org_slug=default
+
+## CI setup
+
+- On CE, the test suite only runs against PostgreSQL by default. We additionally
+ run the suite against MySQL for tags, `master`, and any branch that includes
+ `mysql` in the name.
+- On EE, the test suite always runs both PostgreSQL and MySQL.
## Spinach (feature) tests
@@ -135,3 +496,5 @@ test should be re-implemented using RSpec instead.
---
[Return to Development documentation](README.md)
+
+[^1]: /ci/yaml/README.html#dependencies
diff --git a/doc/development/ui_guide.md b/doc/development/ui_guide.md
index 2d1d504202c..df6ac452300 100644
--- a/doc/development/ui_guide.md
+++ b/doc/development/ui_guide.md
@@ -20,8 +20,8 @@ The content section contains a header and the content itself. The header describ
available to the user in this area. Depending on the area (project, group, profile setting) the header name and navigation may change. For example, when the user visits one of the
project pages the header will contain the project's name and navigation for that project. When the user visits a group page it will contain the group's name and navigation related to this group.
-You can see a visual representation of the navigation in GitLab in the GitLab Product Map, which is located in the [Design Repository](gitlab-map-graffle)
-along with [PDF](gitlab-map-pdf) and [PNG](gitlab-map-png) exports.
+You can see a visual representation of the navigation in GitLab in the GitLab Product Map, which is located in the [Design Repository][gitlab-map-graffle]
+along with [PDF][gitlab-map-pdf] and [PNG][gitlab-map-png] exports.
### Adding new tab to header navigation
@@ -104,4 +104,4 @@ Do not use both green and blue button in one form.
[number_with_delimiter]: http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_with_delimiter
[gitlab-map-graffle]: https://gitlab.com/gitlab-org/gitlab-design/blob/master/production/resources/gitlab-map.graffle
[gitlab-map-pdf]: https://gitlab.com/gitlab-org/gitlab-design/raw/master/production/resources/gitlab-map.pdf
-[gitlab-map-png]: https://gitlab.com/gitlab-org/gitlab-design/raw/master/production/resources/gitlab-map.png \ No newline at end of file
+[gitlab-map-png]: https://gitlab.com/gitlab-org/gitlab-design/raw/master/production/resources/gitlab-map.png
diff --git a/doc/development/ux_guide/animation.md b/doc/development/ux_guide/animation.md
new file mode 100644
index 00000000000..5dae4bcc905
--- /dev/null
+++ b/doc/development/ux_guide/animation.md
@@ -0,0 +1,57 @@
+# Animation
+
+Motion is a tool to help convey important relationships, changes or transitions between elements. It should be used sparingly and intentionally, highlighting the right elements at the right moment.
+
+## Timings
+
+The longer distance an object travel, the timing should be longer for the animation. However, when in doubt, we should avoid large, full screen animations.
+
+Subtle animations, or objects leaving the screen should take **100-200 milliseconds**. Objects entering the screen, or motion we want to use to direct user attention can take between **200-400 milliseconds**. We should avoid animations of longer than 400 milliseconds as they will make the experience appear sluggish. If a specific animation feels like it will need more than 400 milliseconds, revisit the animation to see if there is a simpler, easier, shorter animation to implement.
+
+## Easing
+
+Easing specifies the rate of change of a parameter over time (see [easings.net](http://easings.net/)). Adding an easing curve will make the motion feel more natural. Being consistent with the easing curves will make the whole experience feel more cohesive and connected.
+
+* When an object is entering the screen, or transforming the scale, position, or shape, use the **easeOutQuint** curve (`cubic-bezier(0.23, 1, 0.32, 1)`)
+* When an object is leaving the screen, or transforming the opacity or color, no easing curve is needed. It shouldn't _slow down_ as it is exiting the screen, as that draws attention on the leaving object, where we don't want it. Adding easing to opacity and color transitions will make the motion appear less smooth. Therefore, for these cases, motion should just be **linear**.
+
+## Types of animations
+
+### Hover
+
+Interactive elements (links, buttons, etc.) should have a hover state. A subtle animation for this transition adds a polished feel. We should target a `100ms - 150ms linear` transition for a color hover effect.
+
+View the [interactive example](http://codepen.io/awhildy/full/GNyEvM/) here.
+
+![Hover animation](img/animation-hover.gif)
+
+### Dropdowns
+
+The dropdown menu should feel like it is appearing from the triggering element. Combining a position shift `400ms cubic-bezier(0.23, 1, 0.32, 1)` with a opacity animation `200ms linear` on the second half of the motion achieves this affect.
+
+View the [interactive example](http://codepen.io/awhildy/full/jVLJpb/) here.
+
+![Dropdown animation](img/animation-dropdown.gif)
+
+### Quick update
+
+When information is updating in place, a quick, subtle animation is needed. The previous content should cut out, and the new content should have a quick, `200ms linear` fade in.
+
+![Quick update animation](img/animation-quickupdate.gif)
+
+### Moving transitions
+
+When elements move on screen, there should be a quick animation so it is clear to users what moved where. The timing of this animation differs based on the amount of movement and change. Consider animations between `200ms` and `400ms`.
+
+#### Shifting elements on reorder
+An example of a moving transition is when elements have to move out of the way when you drag an element.
+
+View the [interactive example](http://codepen.io/awhildy/full/ALyKPE/) here.
+
+![Reorder animation](img/animation-reorder.gif)
+
+#### Autoscroll the page
+Another example of a moving transition is when you have to autoscroll the page to keep an active element visible.
+
+View the [interactive example](http://codepen.io/awhildy/full/PbxgVo/) here.
+![Autoscroll animation](img/animation-autoscroll.gif) \ No newline at end of file
diff --git a/doc/development/ux_guide/basics.md b/doc/development/ux_guide/basics.md
new file mode 100644
index 00000000000..a436e9b1948
--- /dev/null
+++ b/doc/development/ux_guide/basics.md
@@ -0,0 +1,84 @@
+# Basics
+
+## Contents
+* [Responsive](#responsive)
+* [Typography](#typography)
+* [Icons](#icons)
+* [Color](#color)
+* [Cursors](#cursors)
+
+---
+
+## Responsive
+GitLab is a responsive experience that works well across all screen sizes, from mobile devices to large monitors. In order to provide a great user experience, the core functionality (browsing files, creating issues, writing comments, etc.) must be available at all resolutions. However, due to size limitations, some secondary functionality may be hidden on smaller screens. Please keep this functionality limited to rare actions that aren't expected to be needed on small devices.
+
+---
+
+## Typography
+### Primary typeface
+GitLab's main typeface used throughout the UI is **Source Sans Pro**. We support both the bold and regular weight.
+
+![Source Sans Pro sample](img/sourcesanspro-sample.png)
+
+
+### Monospace typeface
+This is the typeface used for code blocks and references to commits, branches, and tags (`.commit-sha` or `.ref-name`). GitLab uses the OS default font.
+- **Menlo** (Mac)
+- **Consolas** (Windows)
+- **Liberation Mono** (Linux)
+
+![Monospace font sample](img/monospacefont-sample.png)
+
+---
+
+## Icons
+GitLab uses Font Awesome icons throughout our interface.
+
+| | |
+| :-----------: | :---- |
+| ![Trash icon](img/icon-trash.png) | The trash icon is used for destructive actions that deletes information. |
+| ![Edit icon](img/icon-edit.png) | The pencil icon is used for editing content such as comments.|
+| ![Notification icon](img/icon-notification.png) | The bell icon is for notifications, such as Todos. |
+| ![Subscribe icon](img/icon-subscribe.png) | The eye icon is for subscribing to updates. For example, you can subscribe to a label and get updated on issues with that label. |
+| ![RSS icon](img/icon-rss.png) | The standard RSS icon is used for linking to RSS/atom feeds. |
+| ![Close icon](img/icon-close.png) | An 'x' is used for closing UI elements such as dropdowns. |
+| ![Add icon](img/icon-add.png) | A plus is used when creating new objects, such as issues, projects, etc. |
+
+> TODO: update this section, add more general guidance to icon usage and personality, etc.
+
+---
+
+## Color
+
+| | State | Action |
+| :------: | :------- | :------- |
+| ![Blue](img/color-blue.png) | Primary and active (such as the current tab) | Organizational, managing, and retry commands|
+| ![Green](img/color-green.png) | Opened | Create new objects |
+| ![Orange](img/color-orange.png) | Warning | Non destructive action |
+| ![Red](img/color-red.png) | Closed | Delete and other destructive commands |
+| ![Grey](img/color-grey.png) | Neutral | Neutral secondary commands |
+
+### Text colors
+
+|||
+| :---: | :--- |
+| ![Text primary](img/color-textprimary.png) | Used for primary body text, such as issue description and comment |
+| ![Text secondary](img/color-textsecondary.png) | Used for secondary body text, such as username and date |
+
+> TODO: Establish a perspective for color in terms of our personality and rationalize with Marketing usage.
+
+---
+
+## Cursors
+The mouse cursor is key in helping users understand how to interact with elements on the screen.
+
+| | |
+| :------: | :------- |
+| ![Default cursor](img/cursors-default.png) | Default cursor |
+| ![Pointer cursor](img/cursors-pointer.png) | Pointer cursor: used to indicate that you can click on an element to invoke a command or navigate, such as links and buttons |
+| ![Move cursor](img/cursors-move.png) | Move cursor: used to indicate that you can move an element around on the screen |
+| ![Pan opened cursor](img/cursors-panopened.png) | Pan cursor (opened): indicates that you can grab and move the entire canvas, affecting what is seen in the view port. |
+| ![Pan closed cursor](img/cursors-panclosed.png) | Pan cursor (closed): indicates that you are actively panning the canvas. |
+| ![I-beam cursor](img/cursors-ibeam.png) | I-beam cursor: indicates that this is either text that you can select and copy, or a text field that you can click into to enter text. |
+
+
diff --git a/doc/development/ux_guide/components.md b/doc/development/ux_guide/components.md
new file mode 100644
index 00000000000..ac7c1b6207d
--- /dev/null
+++ b/doc/development/ux_guide/components.md
@@ -0,0 +1,304 @@
+# Components
+
+## Contents
+* [Tooltips](#tooltips)
+* [Anchor links](#anchor-links)
+* [Buttons](#buttons)
+* [Dropdowns](#dropdowns)
+* [Counts](#counts)
+* [Lists](#lists)
+* [Tables](#tables)
+* [Blocks](#blocks)
+* [Panels](#panels)
+* [Alerts](#alerts)
+* [Forms](#forms)
+* [Search box](#search-box)
+* [File holders](#file-holders)
+* [Data formats](#data-formats)
+
+---
+
+## Tooltips
+Tooltips identify elements or provide additional, useful information about the referring elements. Tooltips are different from ALT-attributes, which are intended primarily for static images. Tooltips are summoned by:
+
+* Hovering over an element with a cursor
+* Focusing on an element with a keyboard (usually the tab key)
+* Upon touch
+
+### Usage
+A tooltip should be used:
+* When there isn’t enough space to show the information
+* When it isn’t critical for the user to see the information
+* For icons that don’t have a label
+
+Tooltips shouldn’t repeat information that is shown near the referring element. However, they can show the same data in a different format (e.g. date or timestamps).
+
+![Tooltip usage](img/tooltip-usage.png)
+
+### Placement
+By default, tooltips should be placed below the referring element. However, if there isn’t enough space in the viewport, the tooltip should be moved to the side as needed.
+
+![Tooltip placement location](img/tooltip-placement.png)
+
+---
+
+## Anchor links
+
+Anchor links are used for navigational actions and lone, secondary commands (such as 'Reset filters' on the Issues List) when deemed appropriate by the UX team.
+
+### States
+
+#### Rest
+
+Primary links are blue in their rest state. Secondary links (such as the time stamp on comments) are a neutral gray color in rest. Details on the main GitLab navigation links can be found on the [features](features.md#navigation) page.
+
+#### Hover
+
+On hover, an underline should be added and the color should change. Both the primary and secondary link should become the darker blue color on hover.
+
+#### Focus
+
+The focus state should match the hover state.
+
+![Anchor link states ](img/components-anchorlinks.png)
+
+---
+
+## Buttons
+
+Buttons communicate the command that will occur when the user clicks on them.
+
+### Types
+
+#### Primary
+Primary buttons communicate the main call to action. There should only be one call to action in any given experience. Visually, primary buttons are conveyed with a full background fill
+
+![Primary button example](img/button-primary.png)
+
+#### Secondary
+Secondary buttons are for alternative commands. They should be conveyed by a button with an stroke, and no background fill.
+
+![Secondary button example](img/button-secondary.png)
+
+### Icon and text treatment
+Text should be in sentence case, where only the first word is capitalized. "Create issue" is correct, not "Create Issue". Buttons should only contain an icon or a text, not both.
+
+> TODO: Rationalize this. Ensure that we still believe this.
+
+### Colors
+The default color treatment is the white/grey button. Follow the guidance on the [basics](basics.md#color) page to add meaningful color to a button.
+
+### Secondary states
+
+Primary buttons darken the color of their background and border for hover, focus and active states. An inner shadow is added to the active state to denote the button being pressed.
+
+| Values | Info | Success | Warning | Danger |
+| :------ | :------: | :------: | :------: | :------: |
+| Background: `$color-light` <br> Border: `$border-color-light` | ![](img/button-info--resting.png) | ![](img/button-success--resting.png) | ![](img/button-warning--resting.png) | ![](img/button-danger--resting.png) |
+| Background: `$color-normal` <br> Border: `$border-color-normal` | ![](img/button-info--hover.png) | ![](img/button-success--hover.png) | ![](img/button-warning--hover.png) | ![](img/button-danger--hover.png) |
+| Background: `$color-dark` <br> Border: `$border-color-dark` | ![](img/button-info--active.png) | ![](img/button-success--active.png) | ![](img/button-warning--active.png) | ![](img/button-danger--active.png) |
+
+Since secondary buttons only have a border on their resting state, their hover and focus states add a background color, which gets darkened on active.
+
+| Values | Success Secondary | Close | Spam |
+| :------ | :------: | :------: | :------: |
+| Font: `$border-color-light` <br> Border: `$border-color-light` | ![](img/button-success-secondary--resting.png) | ![](img/button-close--resting.png) | ![](img/button-spam--resting.png) |
+| Background: `$color-light` <br> Border: `$border-color-light` | ![](img/button-success-secondary--hover.png) | ![](img/button-close--hover.png) | ![](img/button-spam--hover.png) |
+| Background: `$color-normal` <br> Border: `$border-color-normal` | ![](img/button-success-secondary--active.png) | ![](img/button-close--active.png) | ![](img/button-spam--active.png) |
+
+### Placement
+
+When there are a group of buttons in a dialog or a form, we need to be consistent with the placement.
+
+#### Dismissive actions on the left
+The dismissive action returns the user to the previous state.
+
+> Example: Cancel
+
+#### Affirmative actions on the right
+Affirmative actions continue to progress towards the user goal that triggered the dialog or form.
+
+> Example: Submit, Ok, Delete
+
+---
+
+
+## Dropdowns
+
+Dropdowns are used to allow users to choose one (or many) options from a list of options. If this list of options is more 20, there should generally be a way to search through and filter the options (see the complex filter dropdowns below.)
+
+> TODO: Will update this section when the new filters UI is implemented.
+
+![Dropdown states](img/components-dropdown.png)
+
+### Max size
+
+The max height for dropdowns should target **10-15** single line items, or **7-10** multi-line items. If the height of the dropdown is too large, the list becomes very hard to parse and it is easy to visually lose track of the item you are looking for. Usability also suffers as more mouse movement is required, and you have a larger area in which you hijack the scroll away from the page level. While it may initially seem counterintuitive to not show as many items as you can, it is actually quicker and easier to process the information when it is cropped at a reasonable height.
+
+---
+
+## Counts
+
+A count element is used in navigation contexts where it is helpful to indicate the count, or number of items, in a list. Always use the [`number_with_delimiter`][number_with_delimiter] helper to display counts in the UI.
+
+![Counts example](img/components-counts.png)
+
+[number_with_delimiter]: http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_with_delimiter
+
+---
+
+## Lists
+
+Lists are used where ever there is a single column of information to display. Ths [issues list](https://gitlab.com/gitlab-org/gitlab-ce/issues) is an example of a important list in the GitLab UI.
+
+### Types
+
+Simple list using .content-list
+
+![Simple list](img/components-simplelist.png)
+
+List with avatar, title and description using .content-list
+
+![List with avatar](img/components-listwithavatar.png)
+
+List with hover effect .well-list
+
+![List with hover effect](img/components-listwithhover.png)
+
+List inside panel
+
+![List inside panel](img/components-listinsidepanel.png)
+
+---
+
+## Tables
+
+When the information is too complex for a list, with multiple columns of information, a table can be used. For example, the [pipelines page](https://gitlab.com/gitlab-org/gitlab-ce/pipelines) uses a table.
+
+![Table](img/components-table.png)
+
+---
+
+## Blocks
+
+Blocks are a way to group related information.
+
+### Types
+
+#### Content blocks
+
+Content blocks (`.content-block`) are the basic grouping of content. They are commonly used in [lists](#lists), and are separated by a botton border.
+
+![Content block](img/components-contentblock.png)
+
+#### Row content blocks
+
+A background color can be added to this blocks. For example, items in the [issue list](https://gitlab.com/gitlab-org/gitlab-ce/issues) have a green background if they were created recently. Below is an example of a gray content block with side padding using `.row-content-block`.
+
+![Row content block](img/components-rowcontentblock.png)
+
+#### Cover blocks
+Cover blocks are generally used to create a heading element for a page, such as a new project, or a user profile page. Below is a cover block (`.cover-block`) for the profile page with an avatar, name and description.
+
+![Cover block](img/components-coverblock.png)
+
+---
+
+## Panels
+
+> TODO: Catalog how we are currently using panels and rationalize how they relate to alerts
+
+![Panels](img/components-panels.png)
+
+---
+
+## Alerts
+
+> TODO: Catalog how we are currently using alerts
+
+![Alerts](img/components-alerts.png)
+
+---
+
+## Forms
+
+There are two options shown below regarding the positioning of labels in forms. Both are options to consider based on context and available size. However, it is important to have a consistent treatment of labels in the same form.
+
+### Types
+
+#### Labels stack vertically
+
+Form (`form`) with label rendered above input.
+
+![Vertical form](img/components-verticalform.png)
+
+#### Labels side-by-side
+
+Horizontal form (`form.horizontal-form`) with label rendered inline with input.
+
+![Horizontal form](img/components-horizontalform.png)
+
+---
+
+## Search box
+
+Search boxes across GitLab have a consistent rest, active and text entered state. When text isn't entered in the box, there should be a magnifying glass right aligned with the input field. When text is entered, the magnifying glass should become a x, allowing users to clear their text.
+
+![Search box](img/components-searchbox.png)
+
+If needed, we indicate the scope of the search in the search box.
+
+![Scoped Search box](img/components-searchboxscoped.png)
+
+---
+
+## File holders
+A file holder (`.file-holder`) is used to show the contents of a file inline on a page of GitLab.
+
+![File Holder component](img/components-fileholder.png)
+
+---
+
+## Data formats
+
+### Dates
+
+#### Exact
+
+Format for exacts dates should be ‘Mon DD, YYYY’, such as the examples below.
+
+![Exact date](img/components-dateexact.png)
+
+#### Relative
+
+This format relates how long since an action has occurred. The exact date can be shown as a tooltip on hover.
+
+![Relative date](img/components-daterelative.png)
+
+### References
+
+Referencing GitLab items depends on a symbol for each type of item. Typing that symbol will invoke a dropdown that allows you to search for and autocomplete the item you were looking for. References are shown as [links](#links) in context, and hovering on them shows the full title or name of the item.
+
+![Hovering on a reference](img/components-referencehover.png)
+
+#### `%` Milestones
+
+![Milestone reference](img/components-referencemilestone.png)
+
+#### `#` Issues
+
+![Issue reference](img/components-referenceissues.png)
+
+#### `!` Merge Requests
+
+![Merge request reference](img/components-referencemrs.png)
+
+#### `~` Labels
+
+![Labels reference](img/components-referencelabels.png)
+
+#### `@` People
+
+![People reference](img/components-referencepeople.png)
+
+> TODO: Open issue: Some commit references use monospace fonts, but others don't. Need to standardize this.
diff --git a/doc/development/ux_guide/copy.md b/doc/development/ux_guide/copy.md
new file mode 100644
index 00000000000..794c8eb6bfe
--- /dev/null
+++ b/doc/development/ux_guide/copy.md
@@ -0,0 +1,188 @@
+# Copy
+
+The copy for GitLab is clear and direct. We strike a clear balance between professional and friendly. We can empathesize with users (such as celebrating completing all Todos), and remain respectful of the importance of the work. We are that trusted, friendly coworker that is helpful and understanding.
+
+The copy and messaging is a core part of the experience of GitLab and the conversation with our users. Follow the below conventions throughout GitLab.
+
+Portions of this page are inspired by work found in the [Material Design guidelines][material design].
+
+>**Note:**
+We are currently inconsistent with this guidance. Images below are created to illustrate the point. As this guidance is refined, we will ensure that our experiences align.
+
+## Contents
+* [Brevity](#brevity)
+* [Capitalization and punctuation](#capitalization-and-punctuation)
+* [Terminology](#terminology)
+
+---
+
+## Brevity
+Users will skim content, rather than read text carefully.
+When familiar with a web app, users rely on muscle memory, and may read even less when moving quickly.
+A good experience should quickly orient a user, regardless of their experience, to the purpose of the current screen. This should happen without the user having to consciously read long strings of text.
+In general, text is burdensome and adds cognitive load. This is especially pronounced in a powerful productivity tool such as GitLab.
+We should _not_ rely on words as a crutch to explain the purpose of a screen.
+The current navigation and composition of the elements on the screen should get the user 95% there, with the remaining 5% being specific elements such as text.
+This means that, as a rule, copy should be very short. A long message or label is a red flag hinting at design that needs improvement.
+
+>**Example:**
+Use `Add` instead of `Add issue` as a button label.
+Preferrably use context and placement of controls to make it obvious what clicking on them will do.
+
+---
+
+## Capitalization and punctuation
+
+### Case
+Use sentence case for titles, headings, labels, menu items, and buttons. Use title case when referring to [features][features] or [products][products]. Note that some features are also objects (e.g. “Merge Requests” and “merge requests”).
+
+| :white_check_mark: Do | :no_entry_sign: Don’t |
+| --- | --- |
+| Add issues to the Issue Board feature in GitLab Hosted | Add Issues To The Issue Board Feature In GitLab Hosted |
+
+### Avoid periods
+Avoid using periods in solitary sentences in these elements:
+
+* Labels
+* Hover text
+* Bulleted lists
+* Dialog body text
+
+Periods should be used for:
+
+* Lists or dialogs with multiple sentences
+* Any sentence followed by a link
+
+| :white_check_mark: **Do** place periods after sentences followed by a link | :no_entry_sign: **Don’t** place periods after a link if it‘s not followed by a sentence |
+| --- | --- |
+| Mention someone to notify them. [Learn more](#) | Mention someone to notify them. [Learn more](#). |
+
+| :white_check_mark: **Do** skip periods after solo sentences of body text | :no_entry_sign: **Don’t** place periods after body text if there is only a single sentence |
+| --- | --- |
+| To see the available commands, enter `/gitlab help` | To see the available commands, enter `/gitlab help`. |
+
+### Use contractions
+Don’t make a sentence harder to understand just to follow this rule. For example, “do not” can give more emphasis than “don’t” when needed.
+
+| :white_check_mark: Do | :no_entry_sign: Don’t |
+| --- | --- |
+| it’s, can’t, wouldn’t, you’re, you’ve, haven’t, don’t | it is, cannot, would not, it’ll, should’ve |
+
+### Use numerals for numbers
+Use “1, 2, 3” instead of “one, two, three” for numbers. One exception is when mixing uses of numbers, such as “Enter two 3s.”
+
+| :white_check_mark: Do | :no_entry_sign: Don’t |
+| --- | --- |
+| 3 new commits | Three new commits |
+
+### Punctuation
+Omit punctuation after phrases and labels to create a cleaner and more readable interface. Use punctuation to add clarity or be grammatically correct.
+
+| Punctuation mark | Copy and paste | HTML entity | Unicode | Mac shortcut | Windows shortcut | Description |
+|---|---|---|---|---|---|---|
+| Period | **.** | | | | | Omit for single sentences in affordances like labels, hover text, bulleted lists, and dialog body text.<br><br>Use in lists or dialogs with multiple sentences, and any sentence followed by a link or inline code.<br><br>Place inside quotation marks unless you’re telling the reader what to enter and it’s ambiguous whether to include the period. |
+| Comma | **,** | | | | | Place inside quotation marks.<br><br>Use a [serial comma][serial comma] in lists of three or more terms. |
+| Exclamation point | **!** | | | | | Avoid exclamation points as they tend to come across as shouting. Some exceptions include greetings or congratulatory messages. |
+| Colon | **:** | `&#58;` | `\u003A` | | | Omit from labels, for example, in the labels for fields in a form. |
+| Apostrophe | **’** | `&rsquo;` | `\u2019` | <kbd>⌥ Option</kbd>+<kbd>⇧ Shift</kbd>+<kbd>]</kbd> | <kbd>Alt</kbd>+<kbd>0 1 4 6</kbd> | Use for contractions (I’m, you’re, ’89) and to show possession.<br><br>To show possession, add an *’s* to all singular common nouns and names, even if they already end in an *s*: “Look into this worker process’s log.” For singular proper names ending in *s*, use only an apostrophe: “James’ commits.” For plurals of a single letter, add an *’s*: “Dot your i’s and cross your t’s.”<br><br>Omit for decades or acronyms: “the 1990s”, “MRs.” |
+| Quotation marks | **“**<br><br>**”**<br><br>**‘**<br><br>**’** | `&ldquo;`<br><br>`&rdquo;`<br><br>`&lsquo;`<br><br>`&rsquo;` | `\u201C`<br><br>`\u201D`<br><br>`\u2018`<br><br>`\u2019` | <kbd>⌥ Option</kbd>+<kbd>[</kbd><br><br><kbd>⌥ Option</kbd>+<kbd>⇧ Shift</kbd>+<kbd>[</kbd><br><br><kbd>⌥ Option</kbd>+<kbd>]</kbd><br><br><kbd>⌥ Option</kbd>+<kbd>⇧ Shift</kbd>+<kbd>]</kbd> | <kbd>Alt</kbd>+<kbd>0 1 4 7</kbd><br><br><kbd>Alt</kbd>+<kbd>0 1 4 8</kbd><br><br><kbd>Alt</kbd>+<kbd>0 1 4 5</kbd><br><br><kbd>Alt</kbd>+<kbd>0 1 4 6</kbd> | Use proper quotation marks (also known as smart quotes, curly quotes, or typographer’s quotes) for quotes. Single quotation marks are used for quotes inside of quotes.<br><br>The right single quotation mark symbol is also used for apostrophes.<br><br>Don’t use primes, straight quotes, or free-standing accents for quotation marks. |
+| Primes | **′**<br><br>**″** | `&prime;`<br><br>`&Prime;` | `\u2032`<br><br>`\u2033` | | <kbd>Alt</kbd>+<kbd>8 2 4 2</kbd><br><br><kbd>Alt</kbd>+<kbd>8 2 4 3</kbd> | Use prime (′) only in abbreviations for feet, arcminutes, and minutes: 3° 15′<br><br>Use double-prime (″) only in abbreviations for inches, arcseconds, and seconds: 3° 15′ 35″<br><br>Don’t use quotation marks, straight quotes, or free-standing accents for primes. |
+| Straight quotes and accents | **"**<br><br>**'**<br><br>**`**<br><br>**´** | `&quot;`<br><br>`&#39;`<br><br>`&#96;`<br><br>`&acute;` | `\u0022`<br><br>`\u0027`<br><br>`\u0060`<br><br>`\u00B4` | | | Don’t use straight quotes or free-standing accents for primes or quotation marks.<br><br>Proper typography never uses straight quotes. They are left over from the age of typewriters and their only modern use is for code. |
+| Ellipsis | **…** | `&hellip;` | | <kbd>⌥ Option</kbd>+<kbd>;</kbd> | <kbd>Alt</kbd>+<kbd>0 1 3 3</kbd> | Use to indicate an action in progress (“Downloading…”) or incomplete or truncated text. No space before the ellipsis.<br><br>Omit from menu items or buttons that open a dialog or start some other process. |
+| Chevrons | **«**<br><br>**»**<br><br>**‹**<br><br>**›**<br><br>**<**<br><br>**>** | `&#171;`<br><br>`&#187;`<br><br>`&#8249;`<br><br>`&#8250;`<br><br>`&lt;`<br><br>`&gt;` | `\u00AB`<br><br>`\u00BB`<br><br>`\u2039`<br><br>`\u203A`<br><br>`\u003C`<br><br>`\u003E`<br><br> | | | Omit from links or buttons that open another page or move to the next or previous step in a process. Also known as angle brackets, angular quote brackets, or guillemets. |
+| Em dash | **—** | `&mdash;` | `\u2014` | <kbd>⌥ Option</kbd>+<kbd>⇧ Shift</kbd>+<kbd>-</kbd> | <kbd>Alt</kbd>+<kbd>0 1 5 1</kbd> | Avoid using dashes to separate text. If you must use dashes for this purpose — like this — use an em dash surrounded by spaces. |
+| En dash | **–** | `&ndash;` | `\u2013` | <kbd>⌥ Option</kbd>+<kbd>-</kbd> | <kbd>Alt</kbd>+<kbd>0 1 5 0</kbd> | Use an en dash without spaces instead of a hyphen to indicate a range of values, such as numbers, times, and dates: “3–5 kg”, “8:00 AM–12:30 PM”, “10–17 Jan” |
+| Hyphen | **-** | | | | | Use to represent negative numbers, or to avoid ambiguity in adjective-noun or noun-participle pairs. Example: “anti-inflammatory”; “5-mile walk.”<br><br>Omit in commonly understood terms and adverbs that end in *ly*: “frontend”, “greatly improved performance.”<br><br>Omit in the term “open source.” |
+| Parentheses | **( )** | | | | | Use only to define acronyms or jargon: “Secure web connections are based on a technology called SSL (the secure sockets layer).”<br><br>Avoid other uses and instead rewrite the text, or use dashes or commas to set off the information. If parentheses are required: If the parenthetical is a complete, independent sentence, place the period inside the parentheses; if not, the period goes outside. |
+
+When using the <kbd>Alt</kbd> keystrokes in Windows, use the numeric keypad, not the row of numbers above the alphabet, and be sure Num Lock is turned on.
+
+---
+
+## Terminology
+Only use the terms below.
+
+When using verbs or adjectives:
+* If the context clearly refers to the object, use them alone. Example: `Edit` or `Closed`
+* If the context isn’t clear enough, use them with the object. Example: `Edit issue` or `Closed issues`
+
+### Projects and Groups
+
+| Term | Use | :no_entry_sign: Don't |
+| ---- | --- | ----- |
+| Members | When discussing the people who are a part of a project or a group. | Don't use `users`. |
+
+### Issues
+
+#### Adjectives (states)
+
+| Term | :no_entry_sign: Don’t |
+| ---- | --- |
+| Open | Don’t use `Pending` or `Created` |
+| Closed | Don’t use `Archived` |
+| Deleted | Don’t use `Removed` or `Trashed` |
+
+#### Verbs (actions)
+
+| Term | Use | :no_entry_sign: Don’t |
+| ---- | --- | --- |
+| New | Although it’s not a verb, `New` is a common standard and used for entering the creation mode of a non-existent issue | Don’t use `Create`, `Open`, or `Add` |
+| Create | Only to indicate when or who created an issue ||
+| Add | Associate an existing issue with an item or a list of items | Don’t use `New` or `Create` |
+| View | Open the detail page of an issue | Don’t use `Open` or `See` |
+| Edit | Enter the editing mode of an issue | Don’t use `Change`, `Modify` or `Update` |
+| Submit | Finalize the *creation* process of an issue | Don’t use `Add`, `Create`, `New`, `Open`, `Save` or `Save changes` |
+| Save | Finalize the *editing* process of an issue | Don’t use `Edit`, `Modify`, `Update`, `Submit`, or `Save changes` |
+| Cancel | Cancel the *creation* or *editing* process of an issue | Don’t use `Back`, `Close`, or `Discard` |
+| Close | Close an open issue | Don’t use `Archive` |
+| Re-open | Re-open a closed issue | Don’t use `Open` |
+| Delete | Permanently remove an issue from the system | Don’t use `Remove` |
+| Remove | Remove the association an issue with an item or a list of items | Don’t use `Delete` |
+
+### Merge requests
+
+#### Adjectives (states)
+
+| Term |
+| ---- |
+| Open |
+| Merged |
+
+#### Verbs (actions)
+
+| Term | Use | :no_entry_sign: Don’t |
+| ---- | --- | --- |
+| Add | Add a merge request | Do not use `create` or `new` |
+| View | View an open or merged merge request ||
+| Edit | Edit an open or merged merge request| Do not use `update` |
+| Approve | Approve an open merge request ||
+| Remove approval, unapproved | Remove approval of an open merge request | Do not use `unapprove` as that is not an English word|
+| Merge | Merge an open merge request ||
+
+### Comments & Discussions
+
+#### Comment
+A **comment** is a written piece of text that users of GitLab can create. Comments have the meta data of author and timestamp. Comments can be added in a variety of contexts, such as issues, merge requests, and discussions.
+
+#### Discussion
+A **discussion** is a group of 1 or more comments. A discussion can include subdiscussions. Some discussions have the special capability of being able to be **resolved**. Both the comments in the discussion and the discussion itself can be resolved.
+
+## Confirmation dialogs
+
+- Destruction buttons should be clear and always say what they are destroying.
+ E.g., `Delete page` instead of just `Delete`.
+- If the copy describes another action the user can take instead of the
+ destructive one, provide a way for them to do that as a secondary button.
+- Avoid the word `cancel` or `canceled` in the descriptive copy. It can be
+ confusing when you then see the `Cancel` button.
+
+---
+
+Portions of this page are modifications based on work created and shared by the [Android Open Source Project][android project] and used according to terms described in the [Creative Commons 2.5 Attribution License][creative commons].
+
+[material design]: https://material.io/guidelines/
+[features]: https://about.gitlab.com/features/ "GitLab features page"
+[products]: https://about.gitlab.com/products/ "GitLab products page"
+[serial comma]: https://en.wikipedia.org/wiki/Serial_comma "“Serial comma” in Wikipedia"
+[android project]: http://source.android.com/
+[creative commons]: http://creativecommons.org/licenses/by/2.5/
diff --git a/doc/development/ux_guide/features.md b/doc/development/ux_guide/features.md
new file mode 100644
index 00000000000..9472995c68c
--- /dev/null
+++ b/doc/development/ux_guide/features.md
@@ -0,0 +1,57 @@
+# Features
+
+## Contents
+* [Navigation](#navigation)
+* [Filtering](#filtering)
+* [Search results](#search-results)
+* [Conversations](#conversations)
+* [Empty states](#empty-states)
+
+---
+
+## Navigation
+
+### Global navigation
+
+The global navigation is accessible via the menu button on the top left of the screen, and can be pinned to keep it open. It contains a consistent list of pages that allow you to view content that is across GitLab. For example, you can view your todos, issues and merge requests across projects and groups.
+
+![Global nav](img/features-globalnav.png)
+
+
+### Contextual navigation
+
+The navigation in the header is contextual to each page. These options change depending on if you are looking at a project, group, or settings page. There should be no more than 10 items on a level in the contextual navigation, allowing it to comfortably fit on a typical laptop screen. There can be up to too levels of navigation. Each sub nav group should be a self-contained group of functionality. For example, everything related to the issue tracker should be under the 'Issue' tab, while everything relating to the wiki will be grouped under the 'Wiki' tab. The names used for each section should be short and easy to remember, ideally 1-2 words in length.
+
+![Contextual nav](img/features-contextualnav.png)
+
+### Information architecture
+
+The [GitLab Product Map](https://gitlab.com/gitlab-org/gitlab-design/raw/master/production/resources/gitlab-map.png) shows a visual representation of the information architecture for GitLab.
+
+---
+
+## Filtering
+
+Today, lists are filtered by a series of dropdowns. Some of these dropdowns allow multiselect (labels), while others allow you to filter to one option (milestones). However, we are currently implementing a [new model](https://gitlab.com/gitlab-org/gitlab-ce/issues/21747) for this, and will update the guide when it is ready.
+
+![Filters](img/features-filters.png)
+
+---
+
+## Search results
+
+### Global search
+
+[Global search](https://gitlab.com/search?group_id=&project_id=13083&repository_ref=&scope=issues&search=mobile) allows you to search across items in a project, or even across multiple projects. You can switch tabs to filter on type of object, or filter by group.
+
+### List search
+
+There are several core lists in the GitLab experience, such as the Issue list and the Merge Request list. You are also able to [filter and search these lists](https://gitlab.com/gitlab-org/gitlab-ce/issues?utf8=%E2%9C%93&search=mobile). This UI will be updated with the [new filtering model](https://gitlab.com/gitlab-org/gitlab-ce/issues/21747).
+
+---
+
+## Empty states
+
+Empty states need to be considered in the design of features. They are vital to helping onboard new users, making the experience feel more approachable and understandable. Empty states should feel inviting and provide just enough information to get people started. There should be a single call to action and a clear explanation of what to use the feature for.
+
+![Empty states](img/features-emptystates.png)
diff --git a/doc/development/ux_guide/img/animation-autoscroll.gif b/doc/development/ux_guide/img/animation-autoscroll.gif
new file mode 100644
index 00000000000..155b0234c64
--- /dev/null
+++ b/doc/development/ux_guide/img/animation-autoscroll.gif
Binary files differ
diff --git a/doc/development/ux_guide/img/animation-dropdown.gif b/doc/development/ux_guide/img/animation-dropdown.gif
new file mode 100644
index 00000000000..c9b31d26165
--- /dev/null
+++ b/doc/development/ux_guide/img/animation-dropdown.gif
Binary files differ
diff --git a/doc/development/ux_guide/img/animation-hover.gif b/doc/development/ux_guide/img/animation-hover.gif
new file mode 100644
index 00000000000..37ad9c76828
--- /dev/null
+++ b/doc/development/ux_guide/img/animation-hover.gif
Binary files differ
diff --git a/doc/development/ux_guide/img/animation-quickupdate.gif b/doc/development/ux_guide/img/animation-quickupdate.gif
new file mode 100644
index 00000000000..8db70bc3d24
--- /dev/null
+++ b/doc/development/ux_guide/img/animation-quickupdate.gif
Binary files differ
diff --git a/doc/development/ux_guide/img/animation-reorder.gif b/doc/development/ux_guide/img/animation-reorder.gif
new file mode 100644
index 00000000000..ccdeb3d396f
--- /dev/null
+++ b/doc/development/ux_guide/img/animation-reorder.gif
Binary files differ
diff --git a/doc/development/ux_guide/img/button-close--active.png b/doc/development/ux_guide/img/button-close--active.png
new file mode 100644
index 00000000000..824bfc8f31b
--- /dev/null
+++ b/doc/development/ux_guide/img/button-close--active.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-close--hover.png b/doc/development/ux_guide/img/button-close--hover.png
new file mode 100644
index 00000000000..0291e121894
--- /dev/null
+++ b/doc/development/ux_guide/img/button-close--hover.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-close--resting.png b/doc/development/ux_guide/img/button-close--resting.png
new file mode 100644
index 00000000000..986d7174ce7
--- /dev/null
+++ b/doc/development/ux_guide/img/button-close--resting.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-danger--active.png b/doc/development/ux_guide/img/button-danger--active.png
new file mode 100644
index 00000000000..d3c64424b26
--- /dev/null
+++ b/doc/development/ux_guide/img/button-danger--active.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-danger--hover.png b/doc/development/ux_guide/img/button-danger--hover.png
new file mode 100644
index 00000000000..8506e093306
--- /dev/null
+++ b/doc/development/ux_guide/img/button-danger--hover.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-danger--resting.png b/doc/development/ux_guide/img/button-danger--resting.png
new file mode 100644
index 00000000000..69ad6bb796b
--- /dev/null
+++ b/doc/development/ux_guide/img/button-danger--resting.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-info--active.png b/doc/development/ux_guide/img/button-info--active.png
new file mode 100644
index 00000000000..23be20b225c
--- /dev/null
+++ b/doc/development/ux_guide/img/button-info--active.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-info--hover.png b/doc/development/ux_guide/img/button-info--hover.png
new file mode 100644
index 00000000000..4cb4e38558c
--- /dev/null
+++ b/doc/development/ux_guide/img/button-info--hover.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-info--resting.png b/doc/development/ux_guide/img/button-info--resting.png
new file mode 100644
index 00000000000..5883340aa83
--- /dev/null
+++ b/doc/development/ux_guide/img/button-info--resting.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-primary.png b/doc/development/ux_guide/img/button-primary.png
new file mode 100644
index 00000000000..eda5ed84aec
--- /dev/null
+++ b/doc/development/ux_guide/img/button-primary.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-secondary.png b/doc/development/ux_guide/img/button-secondary.png
new file mode 100644
index 00000000000..26d4e8cf43d
--- /dev/null
+++ b/doc/development/ux_guide/img/button-secondary.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-spam--active.png b/doc/development/ux_guide/img/button-spam--active.png
new file mode 100644
index 00000000000..55b44898684
--- /dev/null
+++ b/doc/development/ux_guide/img/button-spam--active.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-spam--hover.png b/doc/development/ux_guide/img/button-spam--hover.png
new file mode 100644
index 00000000000..3dc8ed34c54
--- /dev/null
+++ b/doc/development/ux_guide/img/button-spam--hover.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-spam--resting.png b/doc/development/ux_guide/img/button-spam--resting.png
new file mode 100644
index 00000000000..b6bf10a5b64
--- /dev/null
+++ b/doc/development/ux_guide/img/button-spam--resting.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-success--active.png b/doc/development/ux_guide/img/button-success--active.png
new file mode 100644
index 00000000000..895a52831cb
--- /dev/null
+++ b/doc/development/ux_guide/img/button-success--active.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-success--hover.png b/doc/development/ux_guide/img/button-success--hover.png
new file mode 100644
index 00000000000..e4c74bd9778
--- /dev/null
+++ b/doc/development/ux_guide/img/button-success--hover.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-success--resting.png b/doc/development/ux_guide/img/button-success--resting.png
new file mode 100644
index 00000000000..2fa971b5347
--- /dev/null
+++ b/doc/development/ux_guide/img/button-success--resting.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-success-secondary--active.png b/doc/development/ux_guide/img/button-success-secondary--active.png
new file mode 100644
index 00000000000..e7383b36946
--- /dev/null
+++ b/doc/development/ux_guide/img/button-success-secondary--active.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-success-secondary--hover.png b/doc/development/ux_guide/img/button-success-secondary--hover.png
new file mode 100644
index 00000000000..4af2a68cf1b
--- /dev/null
+++ b/doc/development/ux_guide/img/button-success-secondary--hover.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-success-secondary--resting.png b/doc/development/ux_guide/img/button-success-secondary--resting.png
new file mode 100644
index 00000000000..a5a4ec512c8
--- /dev/null
+++ b/doc/development/ux_guide/img/button-success-secondary--resting.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-warning--active.png b/doc/development/ux_guide/img/button-warning--active.png
new file mode 100644
index 00000000000..5877d46c94d
--- /dev/null
+++ b/doc/development/ux_guide/img/button-warning--active.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-warning--hover.png b/doc/development/ux_guide/img/button-warning--hover.png
new file mode 100644
index 00000000000..308e1adc8a3
--- /dev/null
+++ b/doc/development/ux_guide/img/button-warning--hover.png
Binary files differ
diff --git a/doc/development/ux_guide/img/button-warning--resting.png b/doc/development/ux_guide/img/button-warning--resting.png
new file mode 100644
index 00000000000..28e5e601520
--- /dev/null
+++ b/doc/development/ux_guide/img/button-warning--resting.png
Binary files differ
diff --git a/doc/development/ux_guide/img/color-blue.png b/doc/development/ux_guide/img/color-blue.png
new file mode 100644
index 00000000000..844e926f1f5
--- /dev/null
+++ b/doc/development/ux_guide/img/color-blue.png
Binary files differ
diff --git a/doc/development/ux_guide/img/color-green.png b/doc/development/ux_guide/img/color-green.png
new file mode 100644
index 00000000000..5c4c23c7067
--- /dev/null
+++ b/doc/development/ux_guide/img/color-green.png
Binary files differ
diff --git a/doc/development/ux_guide/img/color-grey.png b/doc/development/ux_guide/img/color-grey.png
new file mode 100644
index 00000000000..5247649a0ce
--- /dev/null
+++ b/doc/development/ux_guide/img/color-grey.png
Binary files differ
diff --git a/doc/development/ux_guide/img/color-orange.png b/doc/development/ux_guide/img/color-orange.png
new file mode 100644
index 00000000000..1103c715225
--- /dev/null
+++ b/doc/development/ux_guide/img/color-orange.png
Binary files differ
diff --git a/doc/development/ux_guide/img/color-red.png b/doc/development/ux_guide/img/color-red.png
new file mode 100644
index 00000000000..77ecbbc0a20
--- /dev/null
+++ b/doc/development/ux_guide/img/color-red.png
Binary files differ
diff --git a/doc/development/ux_guide/img/color-textprimary.png b/doc/development/ux_guide/img/color-textprimary.png
new file mode 100644
index 00000000000..90f2821f0cf
--- /dev/null
+++ b/doc/development/ux_guide/img/color-textprimary.png
Binary files differ
diff --git a/doc/development/ux_guide/img/color-textsecondary.png b/doc/development/ux_guide/img/color-textsecondary.png
new file mode 100644
index 00000000000..61cb8a13c45
--- /dev/null
+++ b/doc/development/ux_guide/img/color-textsecondary.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-alerts.png b/doc/development/ux_guide/img/components-alerts.png
new file mode 100644
index 00000000000..66a43ac69e1
--- /dev/null
+++ b/doc/development/ux_guide/img/components-alerts.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-anchorlinks.png b/doc/development/ux_guide/img/components-anchorlinks.png
new file mode 100644
index 00000000000..4a9c730566c
--- /dev/null
+++ b/doc/development/ux_guide/img/components-anchorlinks.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-contentblock.png b/doc/development/ux_guide/img/components-contentblock.png
new file mode 100644
index 00000000000..58d87729701
--- /dev/null
+++ b/doc/development/ux_guide/img/components-contentblock.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-counts.png b/doc/development/ux_guide/img/components-counts.png
new file mode 100644
index 00000000000..19280e988a0
--- /dev/null
+++ b/doc/development/ux_guide/img/components-counts.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-coverblock.png b/doc/development/ux_guide/img/components-coverblock.png
new file mode 100644
index 00000000000..fb135f9648a
--- /dev/null
+++ b/doc/development/ux_guide/img/components-coverblock.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-dateexact.png b/doc/development/ux_guide/img/components-dateexact.png
new file mode 100644
index 00000000000..686ca727293
--- /dev/null
+++ b/doc/development/ux_guide/img/components-dateexact.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-daterelative.png b/doc/development/ux_guide/img/components-daterelative.png
new file mode 100644
index 00000000000..4954dfb51b3
--- /dev/null
+++ b/doc/development/ux_guide/img/components-daterelative.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-dropdown.png b/doc/development/ux_guide/img/components-dropdown.png
new file mode 100644
index 00000000000..7f9a701c089
--- /dev/null
+++ b/doc/development/ux_guide/img/components-dropdown.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-fileholder.png b/doc/development/ux_guide/img/components-fileholder.png
new file mode 100644
index 00000000000..ec2911a1232
--- /dev/null
+++ b/doc/development/ux_guide/img/components-fileholder.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-horizontalform.png b/doc/development/ux_guide/img/components-horizontalform.png
new file mode 100644
index 00000000000..c57dceda43a
--- /dev/null
+++ b/doc/development/ux_guide/img/components-horizontalform.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-listinsidepanel.png b/doc/development/ux_guide/img/components-listinsidepanel.png
new file mode 100644
index 00000000000..3a72d39bb5d
--- /dev/null
+++ b/doc/development/ux_guide/img/components-listinsidepanel.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-listwithavatar.png b/doc/development/ux_guide/img/components-listwithavatar.png
new file mode 100644
index 00000000000..f6db575433c
--- /dev/null
+++ b/doc/development/ux_guide/img/components-listwithavatar.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-listwithhover.png b/doc/development/ux_guide/img/components-listwithhover.png
new file mode 100644
index 00000000000..8521a8ad53e
--- /dev/null
+++ b/doc/development/ux_guide/img/components-listwithhover.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-panels.png b/doc/development/ux_guide/img/components-panels.png
new file mode 100644
index 00000000000..c1391ca07e5
--- /dev/null
+++ b/doc/development/ux_guide/img/components-panels.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencehover.png b/doc/development/ux_guide/img/components-referencehover.png
new file mode 100644
index 00000000000..f80564dbb16
--- /dev/null
+++ b/doc/development/ux_guide/img/components-referencehover.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referenceissues.png b/doc/development/ux_guide/img/components-referenceissues.png
new file mode 100644
index 00000000000..51fb2cf3e43
--- /dev/null
+++ b/doc/development/ux_guide/img/components-referenceissues.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencelabels.png b/doc/development/ux_guide/img/components-referencelabels.png
new file mode 100644
index 00000000000..aba450cc3ba
--- /dev/null
+++ b/doc/development/ux_guide/img/components-referencelabels.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencemilestone.png b/doc/development/ux_guide/img/components-referencemilestone.png
new file mode 100644
index 00000000000..adf2555ccf8
--- /dev/null
+++ b/doc/development/ux_guide/img/components-referencemilestone.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencemrs.png b/doc/development/ux_guide/img/components-referencemrs.png
new file mode 100644
index 00000000000..6c3375f1ea1
--- /dev/null
+++ b/doc/development/ux_guide/img/components-referencemrs.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencepeople.png b/doc/development/ux_guide/img/components-referencepeople.png
new file mode 100644
index 00000000000..b8dd431e2e6
--- /dev/null
+++ b/doc/development/ux_guide/img/components-referencepeople.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-rowcontentblock.png b/doc/development/ux_guide/img/components-rowcontentblock.png
new file mode 100644
index 00000000000..c66a50f9564
--- /dev/null
+++ b/doc/development/ux_guide/img/components-rowcontentblock.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-searchbox.png b/doc/development/ux_guide/img/components-searchbox.png
new file mode 100644
index 00000000000..a25189296ba
--- /dev/null
+++ b/doc/development/ux_guide/img/components-searchbox.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-searchboxscoped.png b/doc/development/ux_guide/img/components-searchboxscoped.png
new file mode 100644
index 00000000000..b116d714848
--- /dev/null
+++ b/doc/development/ux_guide/img/components-searchboxscoped.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-simplelist.png b/doc/development/ux_guide/img/components-simplelist.png
new file mode 100644
index 00000000000..858e5064c25
--- /dev/null
+++ b/doc/development/ux_guide/img/components-simplelist.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-table.png b/doc/development/ux_guide/img/components-table.png
new file mode 100644
index 00000000000..cedc55758a9
--- /dev/null
+++ b/doc/development/ux_guide/img/components-table.png
Binary files differ
diff --git a/doc/development/ux_guide/img/components-verticalform.png b/doc/development/ux_guide/img/components-verticalform.png
new file mode 100644
index 00000000000..489ae6f862f
--- /dev/null
+++ b/doc/development/ux_guide/img/components-verticalform.png
Binary files differ
diff --git a/doc/development/ux_guide/img/cursors-default.png b/doc/development/ux_guide/img/cursors-default.png
new file mode 100644
index 00000000000..c188ec4e351
--- /dev/null
+++ b/doc/development/ux_guide/img/cursors-default.png
Binary files differ
diff --git a/doc/development/ux_guide/img/cursors-ibeam.png b/doc/development/ux_guide/img/cursors-ibeam.png
new file mode 100644
index 00000000000..86f28639982
--- /dev/null
+++ b/doc/development/ux_guide/img/cursors-ibeam.png
Binary files differ
diff --git a/doc/development/ux_guide/img/cursors-move.png b/doc/development/ux_guide/img/cursors-move.png
new file mode 100644
index 00000000000..a9c610eaa88
--- /dev/null
+++ b/doc/development/ux_guide/img/cursors-move.png
Binary files differ
diff --git a/doc/development/ux_guide/img/cursors-panclosed.png b/doc/development/ux_guide/img/cursors-panclosed.png
new file mode 100644
index 00000000000..6d247a765ac
--- /dev/null
+++ b/doc/development/ux_guide/img/cursors-panclosed.png
Binary files differ
diff --git a/doc/development/ux_guide/img/cursors-panopened.png b/doc/development/ux_guide/img/cursors-panopened.png
new file mode 100644
index 00000000000..76f2eeda831
--- /dev/null
+++ b/doc/development/ux_guide/img/cursors-panopened.png
Binary files differ
diff --git a/doc/development/ux_guide/img/cursors-pointer.png b/doc/development/ux_guide/img/cursors-pointer.png
new file mode 100644
index 00000000000..d86dd955fa7
--- /dev/null
+++ b/doc/development/ux_guide/img/cursors-pointer.png
Binary files differ
diff --git a/doc/development/ux_guide/img/features-contextualnav.png b/doc/development/ux_guide/img/features-contextualnav.png
new file mode 100644
index 00000000000..f8466f28627
--- /dev/null
+++ b/doc/development/ux_guide/img/features-contextualnav.png
Binary files differ
diff --git a/doc/development/ux_guide/img/features-emptystates.png b/doc/development/ux_guide/img/features-emptystates.png
new file mode 100644
index 00000000000..51835a7080b
--- /dev/null
+++ b/doc/development/ux_guide/img/features-emptystates.png
Binary files differ
diff --git a/doc/development/ux_guide/img/features-filters.png b/doc/development/ux_guide/img/features-filters.png
new file mode 100644
index 00000000000..41db76db938
--- /dev/null
+++ b/doc/development/ux_guide/img/features-filters.png
Binary files differ
diff --git a/doc/development/ux_guide/img/features-globalnav.png b/doc/development/ux_guide/img/features-globalnav.png
new file mode 100644
index 00000000000..73294d1b524
--- /dev/null
+++ b/doc/development/ux_guide/img/features-globalnav.png
Binary files differ
diff --git a/doc/development/ux_guide/img/harry-robison.png b/doc/development/ux_guide/img/harry-robison.png
new file mode 100644
index 00000000000..702a8b02262
--- /dev/null
+++ b/doc/development/ux_guide/img/harry-robison.png
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-add.png b/doc/development/ux_guide/img/icon-add.png
new file mode 100644
index 00000000000..bcad5e84591
--- /dev/null
+++ b/doc/development/ux_guide/img/icon-add.png
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-close.png b/doc/development/ux_guide/img/icon-close.png
new file mode 100644
index 00000000000..dfe1495f5fa
--- /dev/null
+++ b/doc/development/ux_guide/img/icon-close.png
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-edit.png b/doc/development/ux_guide/img/icon-edit.png
new file mode 100644
index 00000000000..50f6f841868
--- /dev/null
+++ b/doc/development/ux_guide/img/icon-edit.png
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-notification.png b/doc/development/ux_guide/img/icon-notification.png
new file mode 100644
index 00000000000..6ddfaa44f66
--- /dev/null
+++ b/doc/development/ux_guide/img/icon-notification.png
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-rss.png b/doc/development/ux_guide/img/icon-rss.png
new file mode 100644
index 00000000000..b766488b32d
--- /dev/null
+++ b/doc/development/ux_guide/img/icon-rss.png
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-subscribe.png b/doc/development/ux_guide/img/icon-subscribe.png
new file mode 100644
index 00000000000..650168296c6
--- /dev/null
+++ b/doc/development/ux_guide/img/icon-subscribe.png
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-trash.png b/doc/development/ux_guide/img/icon-trash.png
new file mode 100644
index 00000000000..b02178ca992
--- /dev/null
+++ b/doc/development/ux_guide/img/icon-trash.png
Binary files differ
diff --git a/doc/development/ux_guide/img/james-mackey.png b/doc/development/ux_guide/img/james-mackey.png
new file mode 100644
index 00000000000..6db257c5b39
--- /dev/null
+++ b/doc/development/ux_guide/img/james-mackey.png
Binary files differ
diff --git a/doc/development/ux_guide/img/karolina-plaskaty.png b/doc/development/ux_guide/img/karolina-plaskaty.png
new file mode 100644
index 00000000000..2e356c99762
--- /dev/null
+++ b/doc/development/ux_guide/img/karolina-plaskaty.png
Binary files differ
diff --git a/doc/development/ux_guide/img/monospacefont-sample.png b/doc/development/ux_guide/img/monospacefont-sample.png
new file mode 100644
index 00000000000..1cd290b713c
--- /dev/null
+++ b/doc/development/ux_guide/img/monospacefont-sample.png
Binary files differ
diff --git a/doc/development/ux_guide/img/nazim-ramesh.png b/doc/development/ux_guide/img/nazim-ramesh.png
new file mode 100644
index 00000000000..01ba0391630
--- /dev/null
+++ b/doc/development/ux_guide/img/nazim-ramesh.png
Binary files differ
diff --git a/doc/development/ux_guide/img/sourcesanspro-sample.png b/doc/development/ux_guide/img/sourcesanspro-sample.png
new file mode 100644
index 00000000000..f7ecf0c7c66
--- /dev/null
+++ b/doc/development/ux_guide/img/sourcesanspro-sample.png
Binary files differ
diff --git a/doc/development/ux_guide/img/steven-lyons.png b/doc/development/ux_guide/img/steven-lyons.png
new file mode 100644
index 00000000000..2efe1d0b168
--- /dev/null
+++ b/doc/development/ux_guide/img/steven-lyons.png
Binary files differ
diff --git a/doc/development/ux_guide/img/surfaces-contentitemtitle.png b/doc/development/ux_guide/img/surfaces-contentitemtitle.png
new file mode 100644
index 00000000000..3af0b56c8fb
--- /dev/null
+++ b/doc/development/ux_guide/img/surfaces-contentitemtitle.png
Binary files differ
diff --git a/doc/development/ux_guide/img/surfaces-header.png b/doc/development/ux_guide/img/surfaces-header.png
new file mode 100644
index 00000000000..ba616388003
--- /dev/null
+++ b/doc/development/ux_guide/img/surfaces-header.png
Binary files differ
diff --git a/doc/development/ux_guide/img/surfaces-systeminformationblock.png b/doc/development/ux_guide/img/surfaces-systeminformationblock.png
new file mode 100644
index 00000000000..9f42f1d4dd0
--- /dev/null
+++ b/doc/development/ux_guide/img/surfaces-systeminformationblock.png
Binary files differ
diff --git a/doc/development/ux_guide/img/surfaces-ux.png b/doc/development/ux_guide/img/surfaces-ux.png
new file mode 100644
index 00000000000..53208727c64
--- /dev/null
+++ b/doc/development/ux_guide/img/surfaces-ux.png
Binary files differ
diff --git a/doc/development/ux_guide/img/tooltip-placement.png b/doc/development/ux_guide/img/tooltip-placement.png
new file mode 100644
index 00000000000..061f82e4df0
--- /dev/null
+++ b/doc/development/ux_guide/img/tooltip-placement.png
Binary files differ
diff --git a/doc/development/ux_guide/img/tooltip-usage.png b/doc/development/ux_guide/img/tooltip-usage.png
new file mode 100644
index 00000000000..40c4f051cd0
--- /dev/null
+++ b/doc/development/ux_guide/img/tooltip-usage.png
Binary files differ
diff --git a/doc/development/ux_guide/index.md b/doc/development/ux_guide/index.md
new file mode 100644
index 00000000000..8a849f239dc
--- /dev/null
+++ b/doc/development/ux_guide/index.md
@@ -0,0 +1,63 @@
+# GitLab UX Guide
+
+The goal of this guide is to provide standards, principles and in-depth information to design beautiful and effective GitLab features. This will be a living document, and we welcome contributions, feedback and suggestions.
+
+## Design
+
+---
+
+### [Principles](principles.md)
+These guiding principles set a solid foundation for our design system, and should remain relatively stable over multiple releases. They should be referenced as new design patterns are created.
+
+---
+
+### [Basics](basics.md)
+The basic ingredients of our experience establish our personality and feel. This section includes details about typography, iconography, and color.
+
+---
+
+### [Animation](animation.md)
+Guidance on the timing, curving and motion for GitLab.
+
+---
+
+### [Copy](copy.md)
+Conventions on text and messaging within labels, buttons, and other components.
+
+---
+
+### [Components](components.md)
+Components are the controls that make up the GitLab experience, including guidance around buttons, links, dropdowns, etc.
+
+---
+
+### [Surfaces](surfaces.md)
+The GitLab experience is broken apart into several surfaces. Each of these surfaces is designated for a specific scope or type of content. Examples include the header, global menu, side pane, etc.
+
+---
+
+### [Features](features.md)
+The previous building blocks are combined into complete features in the GitLab UX. Examples include our navigation, filters, search results, and empty states.
+
+---
+
+## Research
+
+---
+
+### [Users](users.md)
+How we think about the variety of users of GitLab, from small to large teams, comparing opensource usage to enterprise, etc.
+
+---
+
+## Other
+
+---
+
+### [Tips for designers](tips.md)
+Tips for exporting assets, and other guidance.
+
+---
+
+### [Resources](resources.md)
+Resources for GitLab UX
diff --git a/doc/development/ux_guide/principles.md b/doc/development/ux_guide/principles.md
new file mode 100644
index 00000000000..1a297cba2cc
--- /dev/null
+++ b/doc/development/ux_guide/principles.md
@@ -0,0 +1,17 @@
+# Principles
+
+These are the guiding principles that we should strive for to establish a solid foundation for the GitLab experience.
+
+## Professional and productive
+GitLab is a tool to support what people do, day in, day out. We need to respect the importance of their work, and avoid gimicky details.
+
+## Minimal and efficient
+While work can get complicated, GitLab is about bringing a sharp focus, helping our customers know what matters now.
+
+## Immediately recognizable
+When you look at any screen, you should know immediately that it is GitLab. Our personality is strong and consistent across product and marketing experiences.
+
+## Human and quirky
+We need to build empathy with our users, understanding their state of mind, and connect with them at a human level. Quirkiness is part of our DNA, and we should embrace it in the right moments and contexts.
+
+> TODO: Ensure these principles align well with the goals of the Marketing team
diff --git a/doc/development/ux_guide/resources.md b/doc/development/ux_guide/resources.md
new file mode 100644
index 00000000000..2f760c94414
--- /dev/null
+++ b/doc/development/ux_guide/resources.md
@@ -0,0 +1,13 @@
+# Resources
+
+## GitLab UI development kit
+
+We created a page inside GitLab where you can check commonly used html and css elements.
+
+When you run GitLab instance locally - just visit http://localhost:3000/help/ui page to see UI examples
+you can use during GitLab development.
+
+## Design repository
+
+All design files are stored in the [gitlab-design](https://gitlab.com/gitlab-org/gitlab-design)
+repository and maintained by GitLab UX designers. \ No newline at end of file
diff --git a/doc/development/ux_guide/surfaces.md b/doc/development/ux_guide/surfaces.md
new file mode 100644
index 00000000000..881d6aa4cd6
--- /dev/null
+++ b/doc/development/ux_guide/surfaces.md
@@ -0,0 +1,47 @@
+# Surfaces
+
+## Contents
+* [Header](#header)
+* [Global menu](#global-menu)
+* [Side pane](#side-pane)
+* [Content area](#content-area)
+
+---
+
+![Surfaces UX](img/surfaces-ux.png)
+
+## Global menu
+
+This menu is to navigate to pages that contain content global to GitLab.
+
+---
+
+## Header
+
+The header contains 3 main elements: Project switching and searching, user account avatar and settings, and a contextual menu that changes based on the current page.
+
+![Surfaces Header](img/surfaces-header.png)
+
+---
+
+## Side pane
+
+The side pane holds supporting information and meta data for the information in the content area.
+
+---
+
+## Content area
+
+The main content of the page. The content area can include other surfaces.
+
+### Item title bar
+
+The item title bar contains the top level information to identify the item, such as the name, id and status.
+
+![Item title](img/surfaces-contentitemtitle.png)
+
+### Item system information
+
+The system information block contains relevant system controlled information.
+
+![Item system information](img/surfaces-systeminformationblock.png)
diff --git a/doc/development/ux_guide/tips.md b/doc/development/ux_guide/tips.md
new file mode 100644
index 00000000000..8348de4f8a2
--- /dev/null
+++ b/doc/development/ux_guide/tips.md
@@ -0,0 +1,44 @@
+# Tips
+
+## Contents
+* [SVGs](#svgs)
+
+---
+
+## SVGs
+
+When exporting SVGs, be sure to follow the following guidelines:
+
+1. Convert all strokes to outlines.
+2. Use pathfinder tools to combine overlapping paths and create compound paths.
+3. SVGs that are limited to one color should be exported without a fill color so the color can be set using CSS.
+4. Ensure that exported SVGs have been run through an [SVG cleaner](https://github.com/RazrFalcon/SVGCleaner) to remove unused elements and attributes.
+
+You can open your svg in a text editor to ensure that it is clean.
+Incorrect files will look like this:
+
+```xml
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg width="16px" height="17px" viewBox="0 0 16 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <!-- Generator: Sketch 3.7.2 (28276) - http://www.bohemiancoding.com/sketch -->
+ <title>Group</title>
+ <desc>Created with Sketch.</desc>
+ <defs></defs>
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="Group" fill="#7E7C7C">
+ <path d="M15.1111,1 L0.8891,1 C0.3981,1 0.0001,1.446 0.0001,1.996 L0.0001,15.945 C0.0001,16.495 0.3981,16.941 0.8891,16.941 L15.1111,16.941 C15.6021,16.941 16.0001,16.495 16.0001,15.945 L16.0001,1.996 C16.0001,1.446 15.6021,1 15.1111,1 L15.1111,1 L15.1111,1 Z M14.0001,6.0002 L14.0001,14.949 L2.0001,14.949 L2.0001,6.0002 L14.0001,6.0002 Z M14.0001,4.0002 L14.0001,2.993 L2.0001,2.993 L2.0001,4.0002 L14.0001,4.0002 Z" id="Combined-Shape"></path>
+ <polygon id="Fill-11" points="3 2.0002 5 2.0002 5 0.0002 3 0.0002"></polygon>
+ <polygon id="Fill-16" points="11 2.0002 13 2.0002 13 0.0002 11 0.0002"></polygon>
+ <path d="M5.37709616,11.5511984 L6.92309616,12.7821984 C7.35112915,13.123019 7.97359761,13.0565604 8.32002627,12.6330535 L10.7740263,9.63305349 C11.1237073,9.20557058 11.0606364,8.57555475 10.6331535,8.22587373 C10.2056706,7.87619272 9.57565475,7.93926361 9.22597373,8.36674651 L6.77197373,11.3667465 L8.16890384,11.2176016 L6.62290384,9.98660159 C6.19085236,9.6425813 5.56172188,9.71394467 5.21770159,10.1459962 C4.8736813,10.5780476 4.94504467,11.2071781 5.37709616,11.5511984 L5.37709616,11.5511984 Z" id="Stroke-21"></path>
+ </g>
+ </g>
+</svg>
+```
+
+Correct file will look like this:
+
+```xml
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 17" enable-background="new 0 0 16 17"><path d="m15.1 1h-2.1v-1h-2v1h-6v-1h-2v1h-2.1c-.5 0-.9.5-.9 1v14c0 .6.4 1 .9 1h14.2c.5 0 .9-.4.9-1v-14c0-.5-.4-1-.9-1m-1.1 14h-12v-9h12v9m0-11h-12v-1h12v1"/><path d="m5.4 11.6l1.5 1.2c.4.3 1.1.3 1.4-.1l2.5-3c.3-.4.3-1.1-.1-1.4-.5-.4-1.1-.3-1.5.1l-1.8 2.2-.8-.6c-.4-.3-1.1-.3-1.4.2-.3.4-.3 1 .2 1.4"/></svg>
+```
+
+> TODO: Checkout [https://github.com/svg/svgo](https://github.com/svg/svgo)
diff --git a/doc/development/ux_guide/users.md b/doc/development/ux_guide/users.md
new file mode 100644
index 00000000000..cbd7c17de41
--- /dev/null
+++ b/doc/development/ux_guide/users.md
@@ -0,0 +1,164 @@
+## UX Personas
+* [Nazim Ramesh](#nazim-ramesh)
+ - Small to medium size organisations using GitLab CE
+* [James Mackey](#james-mackey)
+ - Medium to large size organisations using CE or EE
+ - Small organisations using EE
+* [Karolina Plaskaty](#karolina-plaskaty)
+ - Using GitLab.com for personal/hobby projects
+ - Would like to use GitLab at work
+ - Working for a medium to large size organisation
+
+<hr>
+
+### Nazim Ramesh
+- Small to medium size organisations using GitLab CE
+
+<img src="img/nazim-ramesh.png" width="300px">
+
+#### Demographics
+
+- **Age**<br>32 years old
+- **Location**<br>Germany
+- **Education**<br>Bachelor of Science in Computer Science
+- **Occupation**<br>Full-stack web developer
+- **Programming experience**<br>Over 10 years
+- **Frequently used programming languages**<br>JavaScript, SQL, PHP
+- **Hobbies / interests**<br>Functional programming, open source, gaming, web development and web security.
+
+#### Motivations
+Nazim works for a software development company which currently hires around 80 people. When Nazim first joined the company, the engineering team were using Subversion (SVN) as their primary form of source control. However, Nazim felt SVN was not flexible enough to work with many feature branches and noticed that developers with less experience of source control struggled with the central-repository nature of SVN. Armed with a wishlist of features, Nazim began comparing source control tools. A search for “self-hosted Git server repository management” returned GitLab. In his own words, Nazim explains why he wanted the engineering team to start using GitLab:
+
+>
+“I wanted them to switch away from SVN. I needed a server application to manage repositories. The common tools that were around just didn’t meet the requirements. Most of them were too simple or plain...GitLab provided all the required features. Also costs had to be low, since we don’t have a big budget for those things...the Community Edition was perfect in this regard.”
+>
+
+In his role as a full-stack web developer, Nazim could recommend products that he would like the engineering team to use, but final approval lay with his line manager, Mike, VP of Engineering. Nazim recalls that he was met with reluctance from his colleagues when he raised moving to Git and using GitLab.
+
+>
+“The biggest challenge...why should we change anything at all from the status quo? We needed to switch from SVN to Git. They knew they needed to learn Git and a Git workflow...using Git was scary to my colleagues...they thought it was more complex than SVN to use.”
+>
+
+Undeterred, Nazim decided to migrate a couple of projects across to GitLab.
+
+>
+“Old SVN users couldn’t see the benefits of Git at first. It took a month or two to convince them.”
+>
+
+Slowly, by showing his colleagues how easy it was to use Git, the majority of the team’s projects were migrated to GitLab.
+
+The engineering team have been using GitLab CE for around 2 years now. Nazim credits himself as being entirely responsible for his company’s decision to move to GitLab.
+
+#### Frustrations
+##### Adoption to GitLab has been slow
+Not only has the engineering team had to get to grips with Git, they’ve also had to adapt to using GitLab. Due to lack of training and existing skills in other tools, the full feature set of GitLab CE is not being utilised. Nazim sold GitLab to his manager as an ‘all in one’ tool which would replace multiple tools used within the company, thus saving costs. Nazim hasn’t had the time to integrate the legacy tools to GitLab and he’s struggling to convince his peers to change their habits.
+
+##### Missing Features
+Nazim’s company want GitLab to be able to do everything. There isn’t a large budget for software, so they’re selective about what tools are implemented. It needs to add real value to the company. In order for GitLab to be widely adopted and to meet the requirements of different roles within the company, it needs a host of features. When an individual within Nazim’s company wants to know if GitLab has a specific feature or does a particular thing, Nazim is the person to ask. He becomes the point of contact to investigate, build or sometimes just raise the feature request. Nazim gets frustrated when GitLab isn’t able to do what he or his colleagues need it to do.
+
+##### Regressions and bugs
+Nazim often has to calm down his colleagues, when a release contains regressions or new bugs. As he puts it “every new version adds something awesome, but breaks something”. He feels that “old issues for "minor" annoyances get quickly buried in the mass of open issues and linger for a very long time. More generally, I have the feeling that GitLab focus on adding new functionalities, but overlook a bunch of annoying minor regressions or introduced bugs.” Due to limited resource and expertise within the team, not only is it difficult to remain up-to-date with the frequent release cycle, it’s also counterproductive to fix workflows every month.
+
+##### Uses too much RAM and CPU
+>
+“Memory usages mean that if we host it from a cloud based host like AWS, we spend almost as much on the instance as what we would pay GitHub”
+>
+
+##### UI/UX
+GitLab’s interface initially attracted Nazim when he was comparing version control software. He thought it would help his less technical colleagues to adapt to using Git and perhaps, GitLab could be rolled out to other areas of the business, beyond engineering. However, using GitLab’s interface daily has left him frustrated at the lack of personalisation / control over his user experience. He’s also regularly lost in a maze of navigation. Whilst he acknowledges that GitLab listens to its users and that the interface is improving, he becomes annoyed when the changes are too progressive. “Too frequent UI changes. Most of them tend to turn out great after a few cycles of fixes, but the frequency is still far too high for me to feel comfortable to always stay on the current release.”
+
+#### Goals
+* To convince his colleagues to fully adopt GitLab CE, thus improving workflow and collaboration.
+* To use a feature rich version control platform that covers all stages of the development lifecycle, in order to reduce dependencies on other tools.
+* To use an intuitive and stable product, so he can spend more time on his core job responsibilities and less time bug-fixing, guiding colleagues, etc.
+
+<hr>
+
+### James Mackey
+- Medium to large size organisations using CE or EE
+- Small organisations using EE
+
+<img src="img/james-mackey.png" width="300px">
+
+#### Demographics
+
+- **Age**<br>36 years old
+- **Location**<br>US
+- **Education**<br>Masters degree in Computer Science
+- **Occupation**<br>Full-stack web developer
+- **Programming experience**<br>Over 10 years
+- **Frequently used programming languages**<br>JavaScript, SQL, Node.js, Java, PHP, Python
+- **Hobbies / interests**<br>DevOps, open source, web development, science, automation and electronics.
+
+#### Motivations
+James works for a research company which currently hires around 800 staff. He began using GitLab.com back in 2013 for his own open source, hobby projects and loved “the simplicity of installation, administration and use”. After using GitLab for over a year, he began to wonder about using it at work. James explains:
+
+>
+“We first installed the CE edition...on a staging server for a PoC and asked a beta team to use it, specifically for the Merge Request features. Soon other teams began asking us to be beta users too, because the team that was already using GitLab was really enjoying it.”
+>
+
+James and his colleagues also reviewed competitor products including GitHub Enterprise, but they found it “less innovative and with considerable costs...GitLab had the features we wanted at a much lower cost per head than GitHub”.
+
+The company James works for provides employees with a discretionary budget to spend how they want on software, so James and his team decided to upgrade to EE.
+
+James feels partially responsible for his organisation’s decision to start using GitLab.
+
+>
+“It's still up to the teams themselves [to decide] which tools to use. We just had a great experience moving our daily development to GitLab, so other teams have followed the path or are thinking about switching.”
+>
+
+#### Frustrations
+##### Third Party Integration
+Some of GitLab EE’s features are too basic, in particular, issues boards which do not have the level of reporting that James and his team need. Subsequently, they still need to use GitLab EE in conjunction with other tools, such as JIRA. Whilst James feels it isn’t essential for GitLab to meet all his needs (his company are happy for him to use, and pay for, multiple tools), he sometimes isn’t sure what is/isn’t possible with plugins and what level of custom development he and his team will need to do.
+
+##### UX/UI
+James and his team use CI quite heavily for several projects. Whilst they’ve welcomed improvements to the builds and pipelines interface, they still have some difficulty following build process on the different tabs under Pipelines. Some confusion has arisen from not knowing where to find different pieces of information or how to get to the next stages logs from the current stage’s log output screen. They feel more intuitive linking and flow may alleviate the problem. Generally, they feel GitLab’s navigation needs to reviewed and optimised.
+
+##### Permissions
+>
+“There is no granular control over user or group permissions. The permissions for a project are too tightly coupled to the permissions for Gitlab CI/build pipelines.”
+>
+
+#### Goals
+* To be able to integrate third party tools easily with GitLab EE and to create custom integrations and patches where needed.
+* To use GitLab EE primarily for code hosting, merge requests, continuous integration and issue management. James and his team want to be able to understand and use these particular features easily.
+* To able to share one instance of GitLab EE with multiple teams across the business. Advanced user management, the ability to separate permissions on different parts of the source code, etc are important to James.
+
+<hr>
+
+### Karolina Plaskaty
+- Using GitLab.com for personal/hobby projects
+- Would like to use GitLab at work
+- Working for a medium to large size organisation
+
+<img src="img/karolina-plaskaty.png" width="300px">
+
+#### Demographics
+
+- **Age**<br>26 years old
+- **Location**<br>UK
+- **Education**<br>Self taught
+- **Occupation**<br>Junior web-developer
+- **Programming experience**<br>6 years
+- **Frequently used programming languages**<br>JavaScript and SQL
+- **Hobbies / interests**<br>Web development, mobile development, UX, open source, gaming and travel.
+
+#### Motivations
+Karolina has been using GitLab.com for around a year. She roughly spends 8 hours every week programming, of that, 2 hours is spent contributing to open source projects. Karolina contributes to open source projects to gain programming experience and to give back to the community. She likes GitLab.com for its free private repositories and range of features which provide her with everything she needs for her personal projects. Karolina is also a massive fan of GitLab’s values and the fact that it isn’t a “behemoth of a company”. She explains that “displaying every single thing (doc, culture, assumptions, development...) in the open gives me greater confidence to choose Gitlab personally and to recommend it at work.” She’s also an avid reader of GitLab’s blog.
+
+Karolina works for a software development company which currently hires around 500 people. Karolina would love to use GitLab at work but the company has used GitHub Enterprise for a number of years. She describes management at her company as “old fashioned” and explains that it’s “less of a technical issue and more of a cultural issue” to convince upper management to move to GitLab. Karolina is also relatively new to the company so she’s apprehensive about pushing too hard to change version control platforms.
+
+#### Frustrations
+##### Unable to use GitLab at work
+Karolina wants to use GitLab at work but isn’t sure how to approach the subject with management. In her current role, she doesn’t feel that she has the authority to request GitLab.
+
+##### Performance
+GitLab.com is frequently slow and unavailable. Karolina has also heard that GitLab is a “memory hog” which has deterred her from running GitLab on her own machine for just hobby / personal projects.
+
+##### UX/UI
+Karolina has an interest in UX and therefore has strong opinions about how GitLab should look and feel. She feels the interface is cluttered, “it has too many links/buttons” and the navigation “feels a bit weird sometimes. I get lost if I don’t pay attention.” As Karolina also enjoys contributing to open-source projects, it’s important to her that GitLab is well designed for public repositories, she doesn’t feel that GitLab currently achieves this.
+
+#### Goals
+* To develop her programming experience and to learn from other developers.
+* To contribute to both her own and other open source projects.
+* To use a fast and intuitive version control platform. \ No newline at end of file
diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md
index 2574c2c0472..c4830322fa8 100644
--- a/doc/development/what_requires_downtime.md
+++ b/doc/development/what_requires_downtime.md
@@ -2,7 +2,8 @@
When working with a database certain operations can be performed without taking
GitLab offline, others do require a downtime period. This guide describes
-various operations and their impact.
+various operations, their impact, and how to perform them without requiring
+downtime.
## Adding Columns
@@ -41,44 +42,158 @@ information on how to use this method.
## Dropping Columns
-On PostgreSQL you can safely remove an existing column without the need for
-downtime. When you drop a column in PostgreSQL it's not immediately removed,
-instead it is simply disabled. The data is removed on the next vacuum run.
+Removing columns is tricky because running GitLab processes may still be using
+the columns. To work around this you will need two separate merge requests and
+releases: one to ignore and then remove the column, and one to remove the ignore
+rule.
-On MySQL this operation requires downtime.
+### Step 1: Ignoring The Column
-While database wise dropping a column may be fine on PostgreSQL this operation
-still requires downtime because the application code may still be using the
-column that was removed. For example, consider the following migration:
+The first step is to ignore the column in the application code. This is
+necessary because Rails caches the columns and re-uses this cache in various
+places. This can be done by including the `IgnorableColumn` module into the
+model, followed by defining the columns to ignore. For example, to ignore
+`updated_at` in the User model you'd use the following:
```ruby
-class MyMigration < ActiveRecord::Migration
- def change
- remove_column :projects, :dummy
+class User < ActiveRecord::Base
+ include IgnorableColumn
+
+ ignore_column :updated_at
+end
+```
+
+Once added you should create a _post-deployment_ migration that removes the
+column. Both these changes should be submitted in the same merge request.
+
+### Step 2: Removing The Ignore Rule
+
+Once the changes from step 1 have been released & deployed you can set up a
+separate merge request that removes the ignore rule. This merge request can
+simply remove the `ignore_column` line, and the `include IgnorableColumn` line
+if no other `ignore_column` calls remain.
+
+## Renaming Columns
+
+Renaming columns the normal way requires downtime as an application may continue
+using the old column name during/after a database migration. To rename a column
+without requiring downtime we need two migrations: a regular migration, and a
+post-deployment migration. Both these migration can go in the same release.
+
+### Step 1: Add The Regular Migration
+
+First we need to create the regular migration. This migration should use
+`Gitlab::Database::MigrationHelpers#rename_column_concurrently` to perform the
+renaming. For example
+
+```ruby
+# A regular migration in db/migrate
+class RenameUsersUpdatedAtToUpdatedAtTimestamp < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ rename_column_concurrently :users, :updated_at, :updated_at_timestamp
+ end
+
+ def down
+ cleanup_concurrent_column_rename :users, :updated_at_timestamp, :updated_at
end
end
```
-Now imagine that the GitLab instance is running and actively uses the `dummy`
-column. If we were to run the migration this would result in the GitLab instance
-producing errors whenever it tries to use the `dummy` column.
+This will take care of renaming the column, ensuring data stays in sync, copying
+over indexes and foreign keys, etc.
-As a result of the above downtime _is_ required when removing a column, even
-when using PostgreSQL.
+**NOTE:** if a column contains 1 or more indexes that do not contain the name of
+the original column, the above procedure will fail. In this case you will first
+need to rename these indexes.
-## Changing Column Constraints
+### Step 2: Add A Post-Deployment Migration
+
+The renaming procedure requires some cleaning up in a post-deployment migration.
+We can perform this cleanup using
+`Gitlab::Database::MigrationHelpers#cleanup_concurrent_column_rename`:
-Generally changing column constraints requires checking all rows in the table to
-see if they meet the new constraint, unless a constraint is _removed_. For
-example, changing a column that previously allowed NULL values to not allow NULL
-values requires the database to verify all existing rows.
+```ruby
+# A post-deployment migration in db/post_migrate
+class CleanupUsersUpdatedAtRename < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
-The specific behaviour varies a bit between databases but in general the safest
-approach is to assume changing constraints requires downtime.
+ disable_ddl_transaction!
+
+ def up
+ cleanup_concurrent_column_rename :users, :updated_at, :updated_at_timestamp
+ end
+
+ def down
+ rename_column_concurrently :users, :updated_at_timestamp, :updated_at
+ end
+end
+```
+
+## Changing Column Constraints
+
+Adding or removing a NOT NULL clause (or another constraint) can typically be
+done without requiring downtime. However, this does require that any application
+changes are deployed _first_. Thus, changing the constraints of a column should
+happen in a post-deployment migration.
+NOTE: Avoid using `change_column` as it produces inefficient query because it re-defines
+the whole column type. For example, to add a NOT NULL constraint, prefer `change_column_null `
## Changing Column Types
-This operation requires downtime.
+Changing the type of a column can be done using
+`Gitlab::Database::MigrationHelpers#change_column_type_concurrently`. This
+method works similarly to `rename_column_concurrently`. For example, let's say
+we want to change the type of `users.username` from `string` to `text`.
+
+### Step 1: Create A Regular Migration
+
+A regular migration is used to create a new column with a temporary name along
+with setting up some triggers to keep data in sync. Such a migration would look
+as follows:
+
+```ruby
+# A regular migration in db/migrate
+class ChangeUsersUsernameStringToText < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ change_column_type_concurrently :users, :username, :text
+ end
+
+ def down
+ cleanup_concurrent_column_type_change :users, :username
+ end
+end
+```
+
+### Step 2: Create A Post Deployment Migration
+
+Next we need to clean up our changes using a post-deployment migration:
+
+```ruby
+# A post-deployment migration in db/post_migrate
+class ChangeUsersUsernameStringToTextCleanup < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ cleanup_concurrent_column_type_change :users
+ end
+
+ def down
+ change_column_type_concurrently :users, :username, :string
+ end
+end
+```
+
+And that's it, we're done!
## Adding Indexes
@@ -95,12 +210,19 @@ Migrations can take advantage of this by using the method
```ruby
class MyMigration < ActiveRecord::Migration
- def change
+ def up
add_concurrent_index :projects, :column_name
end
+
+ def down
+ remove_index(:projects, :column_name) if index_exists?(:projects, :column_name)
+ end
end
```
+Note that `add_concurrent_index` can not be reversed automatically, thus you
+need to manually define `up` and `down`.
+
When running this on PostgreSQL the `CONCURRENTLY` option mentioned above is
used. On MySQL this method produces a regular `CREATE INDEX` query.
@@ -119,43 +241,54 @@ This operation is safe as there's no code using the table just yet.
## Dropping Tables
-This operation requires downtime as application code may still be using the
-table.
+Dropping tables can be done safely using a post-deployment migration, but only
+if the application no longer uses the table.
## Adding Foreign Keys
-Adding foreign keys acquires an exclusive lock on both the source and target
-tables in PostgreSQL. This requires downtime as otherwise the entire application
-grinds to a halt for the duration of the operation.
+Adding foreign keys usually works in 3 steps:
+
+1. Start a transaction
+1. Run `ALTER TABLE` to add the constraint(s)
+1. Check all existing data
-On MySQL this operation also requires downtime _unless_ foreign key checks are
-disabled. Because this means checks aren't enforced this is not ideal, as such
-one should assume MySQL also requires downtime.
+Because `ALTER TABLE` typically acquires an exclusive lock until the end of a
+transaction this means this approach would require downtime.
+
+GitLab allows you to work around this by using
+`Gitlab::Database::MigrationHelpers#add_concurrent_foreign_key`. This method
+ensures that when PostgreSQL is used no downtime is needed.
## Removing Foreign Keys
-This operation should not require downtime on both PostgreSQL and MySQL.
+This operation does not require downtime.
-## Updating Data
+## Data Migrations
-Updating data should generally be safe. The exception to this is data that's
-being migrated from one version to another while the application still produces
-data in the old version.
+Data migrations can be tricky. The usual approach to migrate data is to take a 3
+step approach:
-For example, imagine the application writes the string `'dog'` to a column but
-it really is meant to write `'cat'` instead. One might think that the following
-migration is all that is needed to solve this problem:
+1. Migrate the initial batch of data
+1. Deploy the application code
+1. Migrate any remaining data
-```ruby
-class MyMigration < ActiveRecord::Migration
- def up
- execute("UPDATE some_table SET column = 'cat' WHERE column = 'dog';")
- end
-end
-```
+Usually this works, but not always. For example, if a field's format is to be
+changed from JSON to something else we have a bit of a problem. If we were to
+change existing data before deploying application code we'll most likely run
+into errors. On the other hand, if we were to migrate after deploying the
+application code we could run into the same problems.
+
+If you merely need to correct some invalid data, then a post-deployment
+migration is usually enough. If you need to change the format of data (e.g. from
+JSON to something else) it's typically best to add a new column for the new data
+format, and have the application use that. In such a case the procedure would
+be:
-Unfortunately this is not enough. Because the application is still running and
-using the old value this may result in the table still containing rows where
-`column` is set to `dog`, even after the migration finished.
+1. Add a new column in the new format
+1. Copy over existing data to this new column
+1. Deploy the application code
+1. In a post-deployment migration, copy over any remaining data
-In these cases downtime _is_ required, even for rarely updated tables.
+In general there is no one-size-fits-all solution, therefore it's best to
+discuss these kind of migrations in a merge request to make sure they are
+implemented in the best way possible.
diff --git a/doc/development/writing_documentation.md b/doc/development/writing_documentation.md
new file mode 100644
index 00000000000..eac9ec2a470
--- /dev/null
+++ b/doc/development/writing_documentation.md
@@ -0,0 +1,105 @@
+# Writing documentation
+
+ - **General Documentation**: written by the developers responsible by creating features. Should be submitted in the same merge request containing code. Feature proposals (by GitLab contributors) should also be accompanied by its respective documentation. They can be later improved by PMs and Technical Writers.
+ - **Technical Articles**: written by any [GitLab Team](https://about.gitlab.com/team/) member, GitLab contributors, or [Community Writers](https://about.gitlab.com/handbook/product/technical-writing/community-writers/).
+ - **Indexes per topic**: initially prepared by the Technical Writing Team, and kept up-to-date by developers and PMs in the same merge request containing code. They gather all resources for that topic in a single page (user and admin documentation, articles, and third-party docs).
+
+## Distinction between General Documentation and Technical Articles
+
+### General documentation
+
+General documentation is categorized by _User_, _Admin_, and _Contributor_, and describe what that feature is, what it does, and its available settings.
+
+### Technical Articles
+
+Technical articles replace technical content that once lived in the [GitLab Blog](https://about.gitlab.com/blog/), where they got out-of-date and weren't easily found.
+
+They are topic-related documentation, written with an user-friendly approach and language, aiming to provide the community with guidance on specific processes to achieve certain objectives.
+
+A technical article guides users and/or admins to achieve certain objectives (within guides and tutorials), or provide an overview of that particular topic or feature (within technical overviews). It can also describe the use, implementation, or integration of third-party tools with GitLab.
+
+They live under `doc/articles/article-title/index.md`, and their images should be placed under `doc/articles/article-title/img/`. Find a list of existing [technical articles](../articles/index.md) here.
+
+#### Types of Technical Articles
+
+- **User guides**: technical content to guide regular users from point A to point B
+- **Admin guides**: technical content to guide administrators of GitLab instances from point A to point B
+- **Technical Overviews**: technical content describing features, solutions, and third-party integrations
+- **Tutorials**: technical content provided step-by-step on how to do things, or how to reach very specific objectives
+
+#### Understanding guides, tutorials, and technical overviews
+
+Suppose there's a process to go from point A to point B in 5 steps: `(A) 1 > 2 > 3 > 4 > 5 (B)`.
+
+A **guide** can be understood as a description of certain processes to achieve a particular objective. A guide brings you from A to B describing the characteristics of that process, but not necessarily going over each step. It can mention, for example, steps 2 and 3, but does not necessarily explain how to accomplish them.
+
+- Live example: "GitLab Pages from A to Z - [Part 1](../user/project/pages/getting_started_part_one.md) to [Part 4](../user/project/pages/getting_started_part_four.md)"
+
+A **tutorial** requires a clear **step-by-step** guidance to achieve a singular objective. It brings you from A to B, describing precisely all the necessary steps involved in that process, showing each of the 5 steps to go from A to B.
+It does not only describes steps 2 and 3, but also shows you how to accomplish them.
+
+- Live example (on the blog): [Hosting on GitLab.com with GitLab Pages](https://about.gitlab.com/2016/04/07/gitlab-pages-setup/)
+
+A **technical overview** is a description of what a certain feature is, and what it does, but does not walk
+through the process of how to use it systematically.
+
+- Live example (on the blog): [GitLab Workflow, an overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/)
+
+#### Special format
+
+Every **Technical Article** contains, in the very beginning, a blockquote with the following information:
+
+- A reference to the **type of article** (user guide, admin guide, tech overview, tutorial)
+- A reference to the **knowledge level** expected from the reader to be able to follow through (beginner, intermediate, advanced)
+- A reference to the **author's name** and **GitLab.com handle**
+- A reference of the **publication date**
+
+```md
+> **Article [Type](../../development/writing_documentation.html#types-of-technical-articles):** tutorial ||
+> **Level:** intermediary ||
+> **Author:** [Name Surname](https://gitlab.com/username) ||
+> **Publication date:** AAAA/MM/DD
+```
+
+#### Technical Articles - Writing Method
+
+Use the [writing method](https://about.gitlab.com/handbook/product/technical-writing/#writing-method) defined by the Technical Writing team.
+
+## Documentation style guidelines
+
+All the docs follow the same [styleguide](doc_styleguide.md).
+
+### Markdown
+
+Currently GitLab docs use Redcarpet as [markdown](../user/markdown.md) engine, but there's an [open discussion](https://gitlab.com/gitlab-com/gitlab-docs/issues/50) for implementing Kramdown in the near future.
+
+## Testing
+
+We try to treat documentation as code, thus have implemented some testing.
+Currently, the following tests are in place:
+
+1. `docs lint`: Check that all internal (relative) links work correctly and
+ that all cURL examples in API docs use the full switches.
+
+If your contribution contains **only** documentation changes, you can speed up
+the CI process by following some branch naming conventions. You have three
+choices:
+
+| Branch name | Valid example |
+| ----------- | ------------- |
+| Starting with `docs/` | `docs/update-api-issues` |
+| Starting with `docs-` | `docs-update-api-issues` |
+| Ending in `-docs` | `123-update-api-issues-docs` |
+
+If your branch name matches any of the above, it will run only the docs
+tests. If it doesn't, the whole test suite will run (including docs).
+
+---
+
+When you submit a merge request to GitLab Community Edition (CE), there is an
+additional job called `rake ee_compat_check` that runs against Enterprise
+Edition (EE) and checks if your changes can apply cleanly to the EE codebase.
+If that job fails, read the instructions in the job log for what to do next.
+Contributors do not need to submit their changes to EE, GitLab Inc. employees
+on the other hand need to make sure that their changes apply cleanly to both
+CE and EE.
diff --git a/doc/downgrade_ee_to_ce/README.md b/doc/downgrade_ee_to_ce/README.md
index a6d22e5a04a..fe4b6d73771 100644
--- a/doc/downgrade_ee_to_ce/README.md
+++ b/doc/downgrade_ee_to_ce/README.md
@@ -15,13 +15,6 @@ Kerberos and Atlassian Crowd are only available on the Enterprise Edition, so
you should disable these mechanisms before downgrading and you should provide
alternative authentication methods to your users.
-### Git Annex
-
-Git Annex is also only available on the Enterprise Edition. This means that if
-you have repositories that use Git Annex to store large files, these files will
-no longer be easily available via Git. You should consider migrating these
-repositories to use Git LFS before downgrading to the Community Edition.
-
### Remove Jenkins CI Service entries from the database
The `JenkinsService` class is only available on the Enterprise Edition codebase,
diff --git a/doc/gitlab-basics/README.md b/doc/gitlab-basics/README.md
index 3aa83975ace..12466437edc 100644
--- a/doc/gitlab-basics/README.md
+++ b/doc/gitlab-basics/README.md
@@ -2,14 +2,14 @@
Step-by-step guides on the basics of working with Git and GitLab.
+- [Command line basics](command-line-commands.md)
- [Start using Git on the command line](start-using-git.md)
- [Create and add your SSH Keys](create-your-ssh-keys.md)
-- [Command Line basics](command-line-commands.md)
- [Create a project](create-project.md)
- [Create a group](create-group.md)
- [Create a branch](create-branch.md)
- [Fork a project](fork-project.md)
- [Add a file](add-file.md)
- [Add an image](add-image.md)
-- [Create a Merge Request](add-merge-request.md)
-- [Create an Issue](create-issue.md)
+- [Create an issue](../user/project/issues/create_new_issue.md)
+- [Create a merge request](add-merge-request.md)
diff --git a/doc/gitlab-basics/add-file.md b/doc/gitlab-basics/add-file.md
index ff10a98e8f5..e9fbcbc23a9 100644
--- a/doc/gitlab-basics/add-file.md
+++ b/doc/gitlab-basics/add-file.md
@@ -1,27 +1,5 @@
# How to add a file
-You can create a file in your [shell](command-line-commands.md) or in GitLab.
-
-To create a file in GitLab, sign in to GitLab.
-
-Select a project on the right side of your screen:
-
-![Select a project](basicsimages/select_project.png)
-
-It's a good idea to [create a branch](create-branch.md), but it's not necessary.
-
-Go to the directory where you'd like to add the file and click on the "+" sign next to the name of the project and directory:
-
-![Create a file](basicsimages/create_file.png)
-
-Name your file (you can't add spaces, so you can use hyphens or underscores). Don't forget to include the markup language you'd like to use :
-
-![File name](basicsimages/file_name.png)
-
-Add all the information that you'd like to include in your file:
-
-![Add information](basicsimages/white_space.png)
-
-Add a commit message based on what you just added and then click on "commit changes":
-
-![Commit changes](basicsimages/commit_changes.png)
+You can create a file in your [terminal](command-line-commands.md) and push
+to GitLab or you can use the
+[web interface](../user/project/repository/web_editor.md#create-a-file).
diff --git a/doc/gitlab-basics/add-image.md b/doc/gitlab-basics/add-image.md
index 476b48a217c..1a44123aa81 100644
--- a/doc/gitlab-basics/add-image.md
+++ b/doc/gitlab-basics/add-image.md
@@ -1,62 +1,56 @@
# How to add an image
-The following are the steps to add images to your repository in
-GitLab:
+Using your standard tool for copying files (e.g. Finder in Mac OS, or Explorer
+in Windows, or...), put the image file into the GitLab project. You can find the
+project as a regular folder in your files.
-Find the image that you’d like to add.
+Go to your [shell](command-line-commands.md), and move into the folder of your
+Gitlab project. This usually means running the following command until you get
+to the desired destination:
-In your computer files, find the GitLab project to which you'd like to add the image
-(you'll find it as a regular file). Click on every file until you find exactly where you'd
-like to add the image. There, paste the image.
-
-Go to your [shell](command-line-commands.md), and add the following commands:
-
-Add this command for every directory that you'd like to open:
```
-cd NAME-OF-FILE-YOU'D-LIKE-TO-OPEN
+cd NAME-OF-FOLDER-YOU'D-LIKE-TO-OPEN
```
-Create a new branch:
-```
-git checkout -b NAME-OF-BRANCH
-```
+Check if your image is actually present in the directory (if you are in Windows,
+use `dir` instead):
-Check if your image was correctly added to the directory:
```
ls
```
You should see the name of the image in the list shown.
-Move up the hierarchy through directories:
-```
-cd ../
-```
+Check the status:
-Check the status and you should see your image’s name in red:
```
git status
```
-Add your changes:
+Your image's name should appear in red, so `git` took notice of it! Now add it
+to the repository:
+
```
git add NAME-OF-YOUR-IMAGE
```
-Check the status and you should see your image’s name in green:
+Check the status again, your image's name should have turned green:
+
```
git status
```
-Add the commit:
+Commit:
+
```
-git commit -m “DESCRIBE COMMIT IN A FEW WORDS”
+git commit -m "DESCRIBE COMMIT IN A FEW WORDS"
```
-Now you can push (send) your changes (in the branch NAME-OF-BRANCH) to GitLab (the git remote named 'origin'):
+Now you can push (send) your changes (in the branch NAME-OF-BRANCH) to GitLab
+(the git remote named 'origin'):
+
```
git push origin NAME-OF-BRANCH
```
-Your image will be added to your branch in your repository in GitLab. Create a [Merge Request](add-merge-request.md)
-to integrate your changes to your project.
+Your image will be added to your branch in your repository in GitLab.
diff --git a/doc/gitlab-basics/add-merge-request.md b/doc/gitlab-basics/add-merge-request.md
index 236b4248ea2..bf01fe51dc3 100644
--- a/doc/gitlab-basics/add-merge-request.md
+++ b/doc/gitlab-basics/add-merge-request.md
@@ -1,42 +1,33 @@
# How to create a merge request
-Merge Requests are useful to integrate separate changes that you've made to a project, on different branches.
+Merge requests are useful to integrate separate changes that you've made to a
+project, on different branches. This is a brief guide on how to create a merge
+request. For more information, check the
+[merge requests documentation](../user/project/merge_requests.md).
-To create a new Merge Request, sign in to GitLab.
+---
-Go to the project where you'd like to merge your changes:
+1. Before you start, you should have already [created a branch](create-branch.md)
+ and [pushed your changes](basic-git-commands.md) to GitLab.
-![Select a project](basicsimages/select_project.png)
+1. You can then go to the project where you'd like to merge your changes and
+ click on the **Merge requests** tab.
-Click on "Merge Requests" on the left side of your screen:
+ ![Merge requests](img/project_navbar.png)
-![Merge requests](basicsimages/merge_requests.png)
+1. Click on **New merge request** on the right side of the screen.
-Click on "+ new Merge Request" on the right side of the screen:
+ ![New Merge Request](img/merge_request_new.png)
-![New Merge Request](basicsimages/new_merge_request.png)
+1. Select a source branch and click on the **Compare branches and continue** button.
-Select a source branch or branch:
+ ![Select a branch](img/merge_request_select_branch.png)
-![Select a branch](basicsimages/select_branch.png)
+1. At a minimum, add a title and a description to your merge request. Optionally,
+ select a user to review your merge request and to accept or close it. You may
+ also select a milestone and labels.
-Click on the "compare branches" button:
+ ![New merge request page](img/merge_request_page.png)
-![Compare branches](basicsimages/compare_branches.png)
-
-Add a title and a description to your Merge Request:
-
-![Add a title and description](basicsimages/title_description_mr.png)
-
-Select a user to review your Merge Request and to accept or close it. You may also select milestones and labels (they are optional). Then click on the "submit new Merge Request" button:
-
-![Add a new merge request](basicsimages/add_new_merge_request.png)
-
-Your Merge Request will be ready to be approved and published.
-
-### Note
-
-After you created a new branch, you'll immediately find a "create a Merge Request" button at the top of your screen.
-You may automatically create a Merge Request from your recently created branch when clicking on this button:
-
-![Automatic MR button](basicsimages/button-create-mr.png)
+1. When ready, click on the **Submit merge request** button. Your merge request
+ will be ready to be approved and published.
diff --git a/doc/gitlab-basics/basicsimages/add_new_merge_request.png b/doc/gitlab-basics/basicsimages/add_new_merge_request.png
deleted file mode 100644
index e60992c4c6a..00000000000
--- a/doc/gitlab-basics/basicsimages/add_new_merge_request.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/add_sshkey.png b/doc/gitlab-basics/basicsimages/add_sshkey.png
deleted file mode 100644
index 89c86018629..00000000000
--- a/doc/gitlab-basics/basicsimages/add_sshkey.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/branch_info.png b/doc/gitlab-basics/basicsimages/branch_info.png
deleted file mode 100644
index 2264f3c5bf2..00000000000
--- a/doc/gitlab-basics/basicsimages/branch_info.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/branch_name.png b/doc/gitlab-basics/basicsimages/branch_name.png
deleted file mode 100644
index 75fe8313611..00000000000
--- a/doc/gitlab-basics/basicsimages/branch_name.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/branches.png b/doc/gitlab-basics/basicsimages/branches.png
deleted file mode 100644
index 8621bc05776..00000000000
--- a/doc/gitlab-basics/basicsimages/branches.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/button-create-mr.png b/doc/gitlab-basics/basicsimages/button-create-mr.png
deleted file mode 100644
index b52ab148839..00000000000
--- a/doc/gitlab-basics/basicsimages/button-create-mr.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/click-on-new-group.png b/doc/gitlab-basics/basicsimages/click-on-new-group.png
deleted file mode 100644
index 6450deec6fc..00000000000
--- a/doc/gitlab-basics/basicsimages/click-on-new-group.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/commit_changes.png b/doc/gitlab-basics/basicsimages/commit_changes.png
deleted file mode 100644
index a88809c5a3f..00000000000
--- a/doc/gitlab-basics/basicsimages/commit_changes.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/commit_message.png b/doc/gitlab-basics/basicsimages/commit_message.png
deleted file mode 100644
index 4abe4517f98..00000000000
--- a/doc/gitlab-basics/basicsimages/commit_message.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/commits.png b/doc/gitlab-basics/basicsimages/commits.png
deleted file mode 100644
index 2bfcaf75f01..00000000000
--- a/doc/gitlab-basics/basicsimages/commits.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/compare_branches.png b/doc/gitlab-basics/basicsimages/compare_branches.png
deleted file mode 100644
index 8a18453dd05..00000000000
--- a/doc/gitlab-basics/basicsimages/compare_branches.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/create_file.png b/doc/gitlab-basics/basicsimages/create_file.png
deleted file mode 100644
index 5ebe1b227dd..00000000000
--- a/doc/gitlab-basics/basicsimages/create_file.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/create_group.png b/doc/gitlab-basics/basicsimages/create_group.png
deleted file mode 100644
index 7ecc3baa990..00000000000
--- a/doc/gitlab-basics/basicsimages/create_group.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/edit_file.png b/doc/gitlab-basics/basicsimages/edit_file.png
deleted file mode 100644
index 9d3e817d036..00000000000
--- a/doc/gitlab-basics/basicsimages/edit_file.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/file_located.png b/doc/gitlab-basics/basicsimages/file_located.png
deleted file mode 100644
index e357cb5c6ab..00000000000
--- a/doc/gitlab-basics/basicsimages/file_located.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/file_name.png b/doc/gitlab-basics/basicsimages/file_name.png
deleted file mode 100644
index 01639c77d0d..00000000000
--- a/doc/gitlab-basics/basicsimages/file_name.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/find_file.png b/doc/gitlab-basics/basicsimages/find_file.png
deleted file mode 100644
index 6f26d26ae18..00000000000
--- a/doc/gitlab-basics/basicsimages/find_file.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/find_group.png b/doc/gitlab-basics/basicsimages/find_group.png
deleted file mode 100644
index 1211510aae9..00000000000
--- a/doc/gitlab-basics/basicsimages/find_group.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/fork.png b/doc/gitlab-basics/basicsimages/fork.png
deleted file mode 100644
index 13ff8345616..00000000000
--- a/doc/gitlab-basics/basicsimages/fork.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/group_info.png b/doc/gitlab-basics/basicsimages/group_info.png
deleted file mode 100644
index 2507d6c295b..00000000000
--- a/doc/gitlab-basics/basicsimages/group_info.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/groups.png b/doc/gitlab-basics/basicsimages/groups.png
deleted file mode 100644
index ef3dca60cc8..00000000000
--- a/doc/gitlab-basics/basicsimages/groups.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/https.png b/doc/gitlab-basics/basicsimages/https.png
deleted file mode 100644
index e74dbc13f9a..00000000000
--- a/doc/gitlab-basics/basicsimages/https.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/image_file.png b/doc/gitlab-basics/basicsimages/image_file.png
deleted file mode 100644
index 7f304b8e1f2..00000000000
--- a/doc/gitlab-basics/basicsimages/image_file.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/issue_title.png b/doc/gitlab-basics/basicsimages/issue_title.png
deleted file mode 100644
index 60a6f7973be..00000000000
--- a/doc/gitlab-basics/basicsimages/issue_title.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/issues.png b/doc/gitlab-basics/basicsimages/issues.png
deleted file mode 100644
index 14e9cdb64e1..00000000000
--- a/doc/gitlab-basics/basicsimages/issues.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/key.png b/doc/gitlab-basics/basicsimages/key.png
deleted file mode 100644
index 04400173ce8..00000000000
--- a/doc/gitlab-basics/basicsimages/key.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/merge_requests.png b/doc/gitlab-basics/basicsimages/merge_requests.png
deleted file mode 100644
index 570164df18b..00000000000
--- a/doc/gitlab-basics/basicsimages/merge_requests.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/new_issue.png b/doc/gitlab-basics/basicsimages/new_issue.png
deleted file mode 100644
index 94e7503dd8b..00000000000
--- a/doc/gitlab-basics/basicsimages/new_issue.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/new_merge_request.png b/doc/gitlab-basics/basicsimages/new_merge_request.png
deleted file mode 100644
index 842f5ebed74..00000000000
--- a/doc/gitlab-basics/basicsimages/new_merge_request.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/new_project.png b/doc/gitlab-basics/basicsimages/new_project.png
deleted file mode 100644
index 421e8bc247b..00000000000
--- a/doc/gitlab-basics/basicsimages/new_project.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/newbranch.png b/doc/gitlab-basics/basicsimages/newbranch.png
deleted file mode 100644
index d5fcf33c4ea..00000000000
--- a/doc/gitlab-basics/basicsimages/newbranch.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/paste_sshkey.png b/doc/gitlab-basics/basicsimages/paste_sshkey.png
deleted file mode 100644
index 578ebee4440..00000000000
--- a/doc/gitlab-basics/basicsimages/paste_sshkey.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/profile_settings.png b/doc/gitlab-basics/basicsimages/profile_settings.png
deleted file mode 100644
index cb3f79f1879..00000000000
--- a/doc/gitlab-basics/basicsimages/profile_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/project_info.png b/doc/gitlab-basics/basicsimages/project_info.png
deleted file mode 100644
index e1adb8d48c2..00000000000
--- a/doc/gitlab-basics/basicsimages/project_info.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/select-group.png b/doc/gitlab-basics/basicsimages/select-group.png
deleted file mode 100644
index 33b978dd899..00000000000
--- a/doc/gitlab-basics/basicsimages/select-group.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/select-group2.png b/doc/gitlab-basics/basicsimages/select-group2.png
deleted file mode 100644
index aee22c638db..00000000000
--- a/doc/gitlab-basics/basicsimages/select-group2.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/select_branch.png b/doc/gitlab-basics/basicsimages/select_branch.png
deleted file mode 100644
index f72a3ffb57f..00000000000
--- a/doc/gitlab-basics/basicsimages/select_branch.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/select_project.png b/doc/gitlab-basics/basicsimages/select_project.png
deleted file mode 100644
index 3bb832ea8d0..00000000000
--- a/doc/gitlab-basics/basicsimages/select_project.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/settings.png b/doc/gitlab-basics/basicsimages/settings.png
deleted file mode 100644
index 78637013d9b..00000000000
--- a/doc/gitlab-basics/basicsimages/settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/shh_keys.png b/doc/gitlab-basics/basicsimages/shh_keys.png
deleted file mode 100644
index c87f11a9d3d..00000000000
--- a/doc/gitlab-basics/basicsimages/shh_keys.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/submit_new_issue.png b/doc/gitlab-basics/basicsimages/submit_new_issue.png
deleted file mode 100644
index 78b854c8903..00000000000
--- a/doc/gitlab-basics/basicsimages/submit_new_issue.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/title_description_mr.png b/doc/gitlab-basics/basicsimages/title_description_mr.png
deleted file mode 100644
index c31d61ec336..00000000000
--- a/doc/gitlab-basics/basicsimages/title_description_mr.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/white_space.png b/doc/gitlab-basics/basicsimages/white_space.png
deleted file mode 100644
index eaa969bdcf4..00000000000
--- a/doc/gitlab-basics/basicsimages/white_space.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/command-line-commands.md b/doc/gitlab-basics/command-line-commands.md
index addd3b6b6eb..2a531193adf 100644
--- a/doc/gitlab-basics/command-line-commands.md
+++ b/doc/gitlab-basics/command-line-commands.md
@@ -4,45 +4,55 @@
In Git, when you copy a project you say you "clone" it. To work on a git project locally (from your own computer), you will need to clone it. To do this, sign in to GitLab.
-When you are on your Dashboard, click on the project that you'd like to clone, which you'll find at the right side of your screen.
+When you are on your Dashboard, click on the project that you'd like to clone.
+To work in the project, you can copy a link to the Git repository through a SSH
+or a HTTPS protocol. SSH is easier to use after it's been
+[setup](create-your-ssh-keys.md). While you are at the **Project** tab, select
+HTTPS or SSH from the dropdown menu and copy the link using the 'Copy to clipboard'
+button (you'll have to paste it on your shell in the next step).
-![Select a project](basicsimages/select_project.png)
-
-To work in the project, you can copy a link to the Git repository through a SSH or a HTTPS protocol. SSH is easier to use after it's been [setup](create-your-ssh-keys.md). When you're in the project, click on the HTTPS or SSH button at the right side of your screen. Then copy the link (you'll have to paste it on your shell in the next step).
-
-![Copy the HTTPS or SSH](basicsimages/https.png)
+![Copy the HTTPS or SSH](img/project_clone_url.png)
## On the command line
### Clone your project
+
Go to your computer's shell and type the following command:
+
```
git clone PASTE HTTPS OR SSH HERE
```
A clone of the project will be created in your computer.
+>**Note:** If you clone your project via an URL that contains special characters, make sure that they are URL-encoded.
+
### Go into a project, directory or file to work in it
+
```
cd NAME-OF-PROJECT-OR-FILE
```
### Go back one directory or file
+
```
cd ../
```
### View what’s in the directory that you are in
+
```
ls
```
### Create a directory
+
```
mkdir NAME-OF-YOUR-DIRECTORY
```
### Create a README.md or file in directory
+
```
touch README.md
nano README.md
@@ -53,27 +63,33 @@ nano README.md
```
### Remove a file
+
```
rm NAME-OF-FILE
```
### Remove a directory and all of its contents
+
```
rm -rf NAME-OF-DIRECTORY
```
### View history in the command line
+
```
history
```
### Carry out commands for which the account you are using lacks authority
+
You will be asked for an administrator’s password.
+
```
sudo
```
### Tell where you are
+
```
pwd
```
diff --git a/doc/gitlab-basics/create-branch.md b/doc/gitlab-basics/create-branch.md
index 7556b0f663e..ad94f0dad29 100644
--- a/doc/gitlab-basics/create-branch.md
+++ b/doc/gitlab-basics/create-branch.md
@@ -2,38 +2,11 @@
A branch is an independent line of development.
-New commits are recorded in the history for the current branch, which results in taking the source from someone’s repository (the place where the history of your work is stored) at certain point in time, and apply your own changes to it in the history of the project.
-
-To add changes to your GitLab project, you should create a branch. You can do it in your [shell](basic-git-commands.md) or in GitLab.
-
-To create a new branch in GitLab, sign in and then select a project on the right side of your screen:
-
-![Select a project](basicsimages/select_project.png)
-
-Click on "commits" on the menu on the left side of your screen:
-
-![Commits](basicsimages/commits.png)
-
-Click on the "branches" tab:
-
-![Branches](basicsimages/branches.png)
-
-Click on the "new branch" button on the right side of the screen:
-
-![New branch](basicsimages/newbranch.png)
-
-Fill out the information required:
-
-1. Add a name for your new branch (you can't add spaces, so you can use hyphens or underscores)
-
-1. On the "create from" space, add the the name of the branch you want to branch off from
-
-1. Click on the button "create branch"
-
-![Branch info](basicsimages/branch_info.png)
-
-### Note:
-
-You will be able to find and select the name of your branch in the white box next to a project's name:
-
-![Branch name](basicsimages/branch_name.png)
+New commits are recorded in the history for the current branch, which results
+in taking the source from someone’s repository (the place where the history of
+your work is stored) at certain point in time, and apply your own changes to it
+in the history of the project.
+
+To add changes to your GitLab project, you should create a branch. You can do
+it in your [terminal](basic-git-commands.md) or by
+[using the web interface](../user/project/repository/web_editor.md#create-a-new-branch).
diff --git a/doc/gitlab-basics/create-group.md b/doc/gitlab-basics/create-group.md
index f80ae62e442..b4889bb8818 100644
--- a/doc/gitlab-basics/create-group.md
+++ b/doc/gitlab-basics/create-group.md
@@ -1,43 +1,50 @@
# How to create a group in GitLab
-## Create a group
-
Your projects in GitLab can be organized in 2 different ways:
-under your own namespace for single projects, such as ´your-name/project-1'; or under groups.
-If you organize your projects under a group, it works like a folder. You can manage your group members' permissions and access to the projects.
-
-To create a group, follow the instructions below:
+under your own namespace for single projects, such as `your-name/project-1` or
+under groups.
-Sign in to [GitLab.com](https://gitlab.com).
+If you organize your projects under a group, it works like a folder. You can
+manage your group members' permissions and access to the projects.
-When you are on your Dashboard, click on "Groups" on the left menu of your screen:
+---
-![Go to groups](basicsimages/select-group2.png)
+To create a group:
-Click on "New group" on the top right side of your screen:
+1. Expand the left sidebar by clicking the three bars at the upper left corner
+ and then navigate to **Groups**.
-![New group](basicsimages/click-on-new-group.png)
+ ![Go to groups](img/create_new_group_sidebar.png)
-Fill out the information required:
+1. Once in your groups dashboard, click on **New group**.
-1. Add a group path or group name (you can't add spaces, so you can use hyphens or underscores)
+ ![Create new group information](img/create_new_group_info.png)
-1. Add details or a group description
+1. Fill out the needed information:
-1. You can choose a group avatar if you'd like
+ 1. Set the "Group path" which will be the namespace under which your projects
+ will be hosted (path can contain only letters, digits, underscores, dashes
+ and dots; it cannot start with dashes or end in dot).
+ 1. The "Group name" will populate with the path. Optionally, you can change
+ it. This is the name that will display in the group views.
+ 1. Optionally, you can add a description so that others can briefly understand
+ what this group is about.
+ 1. Optionally, choose and avatar for your project.
+ 1. Choose the [visibility level](../public_access/public_access.md).
-1. Click on "create group"
+1. Finally, click the **Create group** button.
-![Group information](basicsimages/group_info.png)
-
-## Add a project to a group
+## Add a new project to a group
There are 2 different ways to add a new project to a group:
-* Select a group and then click on "New project" on the right side of your screen. Then you can [create a project](create-project.md)
+- Select a group and then click on the **New project** button.
+
+ ![New project](img/create_new_project_from_group.png)
-![New project](basicsimages/new_project.png)
+ You can then continue on [creating a project](create-project.md).
-* When you are [creating a project](create-project.md), click on "create a group" on the bottom right side of your screen
+- While you are [creating a project](create-project.md), select a group namespace
+ you've already created from the dropdown menu.
-![Create a group](basicsimages/create_group.png)
+ ![Select group](img/select_group_dropdown.png)
diff --git a/doc/gitlab-basics/create-issue.md b/doc/gitlab-basics/create-issue.md
index da9a165b8f5..abb163dbf18 100644
--- a/doc/gitlab-basics/create-issue.md
+++ b/doc/gitlab-basics/create-issue.md
@@ -1,27 +1,2 @@
-# How to create an Issue in GitLab
-The Issue Tracker is a good place to add things that need to be improved or solved in a project.
-
-To create an Issue, sign in to GitLab.
-
-Go to the project where you'd like to create the Issue:
-
-![Select a project](basicsimages/select_project.png)
-
-Click on "Issues" on the left side of your screen:
-
-![Issues](basicsimages/issues.png)
-
-Click on the "+ new issue" button on the right side of your screen:
-
-![New issue](basicsimages/new_issue.png)
-
-Add a title and a description to your issue:
-
-![Issue title and description](basicsimages/issue_title.png)
-
-You may assign the Issue to a user, add a milestone and add labels (they are all optional). Then click on "submit new issue":
-
-![Submit new issue](basicsimages/submit_new_issue.png)
-
-Your Issue will now be added to the Issue Tracker and will be ready to be reviewed. You can comment on it and mention the people involved. You can also link Issues to the Merge Requests where the Issues are solved. To do this, you can use an [Issue closing pattern](../user/project/issues/automatic_issue_closing.md).
+This document was moved to [another location](../user/project/issues/index.md#new-issue).
diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md
index f737dffc024..2513f4b420a 100644
--- a/doc/gitlab-basics/create-project.md
+++ b/doc/gitlab-basics/create-project.md
@@ -1,21 +1,28 @@
# How to create a project in GitLab
-To create a new project, sign in to GitLab.
+1. In your dashboard, click the green **New project** button or use the plus
+ icon in the upper right corner of the navigation bar.
-Go to your Dashboard and click on "new project" on the right side of your screen.
+ ![Create a project](img/create_new_project_button.png)
-![Create a project](basicsimages/new_project.png)
+1. This opens the **New project** page.
-Fill out the required information:
+ ![Project information](img/create_new_project_info.png)
-1. Project path or the name of your project (you can't add spaces, so you can use hyphens or underscores)
+1. Provide the following information:
+ - Enter the name of your project in the **Project name** field. You can't use
+ special characters, but you can use spaces, hyphens, underscores or even
+ emoji.
+ - If you have a project in a different repository, you can [import it] by
+ clicking an **Import project from** button provided this is enabled in
+ your GitLab instance. Ask your administrator if not.
+ - The **Project description (optional)** field enables you to enter a
+ description for your project's dashboard, which will help others
+ understand what your project is about. Though it's not required, it's a good
+ idea to fill this in.
+ - Changing the **Visibility Level** modifies the project's
+ [viewing and access rights](../public_access/public_access.md) for users.
-1. Your project's description
+1. Click **Create project**.
-1. Select a [visibility level](https://gitlab.com/help/public_access/public_access)
-
-1. You can also [import your existing projects](http://docs.gitlab.com/ce/workflow/importing/README.html)
-
-1. Click on "create project"
-
-!![Project information](basicsimages/project_info.png)
+[import it]: ../workflow/importing/README.md
diff --git a/doc/gitlab-basics/create-your-ssh-keys.md b/doc/gitlab-basics/create-your-ssh-keys.md
index f31c353f2cf..b6ebe374de3 100644
--- a/doc/gitlab-basics/create-your-ssh-keys.md
+++ b/doc/gitlab-basics/create-your-ssh-keys.md
@@ -1,33 +1,37 @@
# How to create your SSH Keys
-You need to connect your computer to your GitLab account through SSH Keys. They are unique for every computer that you link your GitLab account with.
+1. The first thing you need to do is go to your [command line](start-using-git.md)
+ and follow the [instructions](../ssh/README.md) to generate your SSH key pair.
-## Generate your SSH Key
+1. Once you do that, login to GitLab with your credentials.
+1. On the upper right corner, click on your avatar and go to your **Profile settings**.
-Create an account on GitLab. Sign up and check your email for your confirmation link.
+ ![Profile settings dropdown](img/profile_settings.png)
-After you confirm, go to GitLab and sign in to your account.
+1. Navigate to the **SSH keys** tab.
-## Add your SSH Key
+ ![SSH Keys](img/profile_settings_ssh_keys.png)
-On the left side menu, click on "profile settings" and then click on "SSH Keys":
+3. Paste your **public** key that you generated in the first step in the 'Key'
+ box.
-![SSH Keys](basicsimages/shh_keys.png)
+ ![Paste SSH public key](img/profile_settings_ssh_keys_paste_pub.png)
-Then click on the green button "Add SSH Key":
+1. Optionally, give it a descriptive title so that you can recognize it in the
+ event you add multiple keys.
-![Add SSH Key](basicsimages/add_sshkey.png)
+ ![SSH key title](img/profile_settings_ssh_keys_title.png)
-There, you should paste the SSH Key that your command line will generate for you. Below you'll find the steps to generate it:
+1. Finally, click on **Add key** to add it to GitLab. You will be able to see
+ its fingerprint, its title and creation date.
-![Paste SSH Key](basicsimages/paste_sshkey.png)
+ ![SSH key single page](img/profile_settings_ssh_keys_single_key.png)
-## To generate an SSH Key on your command line
-Go to your [command line](start-using-git.md) and follow the [instructions](../ssh/README.md) to generate it.
+>**Note:**
+Once you add a key, you cannot edit it, only remove it. In case the paste
+didn't work, you will have to remove the offending key and re-add it.
-Copy the SSH Key that your command line created and paste it on the "Key" box on the GitLab page. The title will be added automatically.
+---
-![Paste SSH Key](basicsimages/key.png)
-
-Now, you'll be able to use Git over SSH, instead of Git over HTTP.
+Congratulations! You are now ready to use Git over SSH, instead of Git over HTTP!
diff --git a/doc/gitlab-basics/fork-project.md b/doc/gitlab-basics/fork-project.md
index 5f8b81ea919..6c232fe6086 100644
--- a/doc/gitlab-basics/fork-project.md
+++ b/doc/gitlab-basics/fork-project.md
@@ -1,19 +1,20 @@
# How to fork a project
-A fork is a copy of an original repository that you can put somewhere else
-or where you can experiment and apply changes that you can later decide if
+A fork is a copy of an original repository that you can put in another namespace
+where you can experiment and apply changes that you can later decide if
publishing or not, without affecting your original project.
It takes just a few steps to fork a project in GitLab.
-Sign in to GitLab.
+1. Go to a project's dashboard under the **Project** tab and click on the
+ **Fork** button.
-Select a project on the right side of your screen:
+ ![Click on Fork button](img/fork_new.png)
-![Select a project](basicsimages/select_project.png)
+1. You will be asked where to fork the repository. Click on the user or group
+ to where you'd like to add the forked project.
-Click on the "fork" button on the right side of your screen:
+ ![Choose namespace](img/fork_choose_namespace.png)
-![Fork](basicsimages/fork.png)
-
-Click on the user or group to where you'd like to add the forked project.
+1. After a few moments, depending on the repository's size, the forking will
+ complete.
diff --git a/doc/gitlab-basics/img/create_new_group_info.png b/doc/gitlab-basics/img/create_new_group_info.png
new file mode 100644
index 00000000000..8d2501d9f7a
--- /dev/null
+++ b/doc/gitlab-basics/img/create_new_group_info.png
Binary files differ
diff --git a/doc/gitlab-basics/img/create_new_group_sidebar.png b/doc/gitlab-basics/img/create_new_group_sidebar.png
new file mode 100644
index 00000000000..fa88d1d51c0
--- /dev/null
+++ b/doc/gitlab-basics/img/create_new_group_sidebar.png
Binary files differ
diff --git a/doc/gitlab-basics/img/create_new_project_button.png b/doc/gitlab-basics/img/create_new_project_button.png
new file mode 100644
index 00000000000..567f104880f
--- /dev/null
+++ b/doc/gitlab-basics/img/create_new_project_button.png
Binary files differ
diff --git a/doc/gitlab-basics/img/create_new_project_from_group.png b/doc/gitlab-basics/img/create_new_project_from_group.png
new file mode 100644
index 00000000000..c35234660db
--- /dev/null
+++ b/doc/gitlab-basics/img/create_new_project_from_group.png
Binary files differ
diff --git a/doc/gitlab-basics/img/create_new_project_info.png b/doc/gitlab-basics/img/create_new_project_info.png
new file mode 100644
index 00000000000..fcfbca87b91
--- /dev/null
+++ b/doc/gitlab-basics/img/create_new_project_info.png
Binary files differ
diff --git a/doc/gitlab-basics/img/fork_choose_namespace.png b/doc/gitlab-basics/img/fork_choose_namespace.png
new file mode 100644
index 00000000000..4c50276d5ad
--- /dev/null
+++ b/doc/gitlab-basics/img/fork_choose_namespace.png
Binary files differ
diff --git a/doc/gitlab-basics/img/fork_new.png b/doc/gitlab-basics/img/fork_new.png
new file mode 100644
index 00000000000..fa185fdaca1
--- /dev/null
+++ b/doc/gitlab-basics/img/fork_new.png
Binary files differ
diff --git a/doc/gitlab-basics/img/merge_request_new.png b/doc/gitlab-basics/img/merge_request_new.png
new file mode 100644
index 00000000000..6fcd7bebada
--- /dev/null
+++ b/doc/gitlab-basics/img/merge_request_new.png
Binary files differ
diff --git a/doc/gitlab-basics/img/merge_request_page.png b/doc/gitlab-basics/img/merge_request_page.png
new file mode 100644
index 00000000000..f6087294e22
--- /dev/null
+++ b/doc/gitlab-basics/img/merge_request_page.png
Binary files differ
diff --git a/doc/gitlab-basics/img/merge_request_select_branch.png b/doc/gitlab-basics/img/merge_request_select_branch.png
new file mode 100644
index 00000000000..9f6b93943a9
--- /dev/null
+++ b/doc/gitlab-basics/img/merge_request_select_branch.png
Binary files differ
diff --git a/doc/gitlab-basics/img/new_issue_button.png b/doc/gitlab-basics/img/new_issue_button.png
new file mode 100644
index 00000000000..3b113471f0c
--- /dev/null
+++ b/doc/gitlab-basics/img/new_issue_button.png
Binary files differ
diff --git a/doc/gitlab-basics/img/new_issue_page.png b/doc/gitlab-basics/img/new_issue_page.png
new file mode 100644
index 00000000000..ce3e60df276
--- /dev/null
+++ b/doc/gitlab-basics/img/new_issue_page.png
Binary files differ
diff --git a/doc/gitlab-basics/img/profile_settings.png b/doc/gitlab-basics/img/profile_settings.png
new file mode 100644
index 00000000000..aaa1a39313d
--- /dev/null
+++ b/doc/gitlab-basics/img/profile_settings.png
Binary files differ
diff --git a/doc/gitlab-basics/img/profile_settings_ssh_keys.png b/doc/gitlab-basics/img/profile_settings_ssh_keys.png
new file mode 100644
index 00000000000..8ac603a2af9
--- /dev/null
+++ b/doc/gitlab-basics/img/profile_settings_ssh_keys.png
Binary files differ
diff --git a/doc/gitlab-basics/img/profile_settings_ssh_keys_paste_pub.png b/doc/gitlab-basics/img/profile_settings_ssh_keys_paste_pub.png
new file mode 100644
index 00000000000..5e501ec86ef
--- /dev/null
+++ b/doc/gitlab-basics/img/profile_settings_ssh_keys_paste_pub.png
Binary files differ
diff --git a/doc/gitlab-basics/img/profile_settings_ssh_keys_single_key.png b/doc/gitlab-basics/img/profile_settings_ssh_keys_single_key.png
new file mode 100644
index 00000000000..7ebb8973ef0
--- /dev/null
+++ b/doc/gitlab-basics/img/profile_settings_ssh_keys_single_key.png
Binary files differ
diff --git a/doc/gitlab-basics/img/profile_settings_ssh_keys_title.png b/doc/gitlab-basics/img/profile_settings_ssh_keys_title.png
new file mode 100644
index 00000000000..89a04c17fed
--- /dev/null
+++ b/doc/gitlab-basics/img/profile_settings_ssh_keys_title.png
Binary files differ
diff --git a/doc/gitlab-basics/img/project_clone_url.png b/doc/gitlab-basics/img/project_clone_url.png
new file mode 100644
index 00000000000..bdd7d011db3
--- /dev/null
+++ b/doc/gitlab-basics/img/project_clone_url.png
Binary files differ
diff --git a/doc/gitlab-basics/img/project_navbar.png b/doc/gitlab-basics/img/project_navbar.png
new file mode 100644
index 00000000000..be6f38ede32
--- /dev/null
+++ b/doc/gitlab-basics/img/project_navbar.png
Binary files differ
diff --git a/doc/gitlab-basics/basicsimages/public_file_link.png b/doc/gitlab-basics/img/public_file_link.png
index f60df6807f4..f60df6807f4 100644
--- a/doc/gitlab-basics/basicsimages/public_file_link.png
+++ b/doc/gitlab-basics/img/public_file_link.png
Binary files differ
diff --git a/doc/gitlab-basics/img/select_group_dropdown.png b/doc/gitlab-basics/img/select_group_dropdown.png
new file mode 100644
index 00000000000..68fc950304c
--- /dev/null
+++ b/doc/gitlab-basics/img/select_group_dropdown.png
Binary files differ
diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md
index b61f436c1a4..42cd8bb3e48 100644
--- a/doc/gitlab-basics/start-using-git.md
+++ b/doc/gitlab-basics/start-using-git.md
@@ -1,11 +1,10 @@
# Start using Git on the command line
-If you want to start using a Git and GitLab, make sure that you have created an
-account on GitLab.
+If you want to start using Git and GitLab, make sure that you have created and/or signed into an account on GitLab.
## Open a shell
-Depending on your operating system, find the shell of your preference. Here are some suggestions.
+Depending on your operating system, you will need to use a shell of your preference. Here are some suggestions:
- [Terminal](http://blog.teamtreehouse.com/introduction-to-the-mac-os-x-command-line) on Mac OSX
@@ -22,19 +21,19 @@ Type the following command and then press enter:
git --version
```
-You should receive a message that will tell you which Git version you have in your computer. If you don’t receive a "Git version" message, it means that you need to [download Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).
+You should receive a message that will tell you which Git version you have on your computer. If you don’t receive a "Git version" message, it means that you need to [download Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).
If Git doesn't automatically download, there's an option on the website to [download manually](https://git-scm.com/downloads). Then follow the steps on the installation window.
-After you finished installing, open a new shell and type "git --version" again to verify that it was correctly installed.
+After you are finished installing, open a new shell and type "git --version" again to verify that it was correctly installed.
## Add your Git username and set your email
-It is important because every Git commit that you create will use this information.
+It is important to configure your Git username and email address as every Git commit will use this information to identify you as the author.
On your shell, type the following command to add your username:
```
-git config --global user.name ADD YOUR USERNAME
+git config --global user.name "YOUR_USERNAME"
```
Then verify that you have the correct username:
@@ -44,7 +43,7 @@ git config --global user.name
To set your email address, type the following command:
```
-git config --global user.email ADD YOUR EMAIL
+git config --global user.email "your_email_address@example.com"
```
To verify that you entered your email correctly, type:
@@ -52,7 +51,7 @@ To verify that you entered your email correctly, type:
git config --global user.email
```
-You'll need to do this only once because you are using the "--global" option. It tells Git to always use this information for anything you do on that system. If you want to override this with a different username or email address for specific projects, you can run the command without the "--global" option when you’re in that project.
+You'll need to do this only once as you are using the `--global` option. It tells Git to always use this information for anything you do on that system. If you want to override this with a different username or email address for specific projects, you can run the command without the `--global` option when you’re in that project.
## Check your information
@@ -76,7 +75,7 @@ git pull REMOTE NAME-OF-BRANCH -u
(REMOTE: origin) (NAME-OF-BRANCH: could be "master" or an existing branch)
### Create a branch
-Spaces won't be recognized, so you need to use a hyphen or underscore.
+Spaces won't be recognized, so you will need to use a hyphen or underscore.
```
git checkout -b NAME-OF-BRANCH
```
@@ -127,4 +126,3 @@ You need to be in the master branch.
git checkout master
git merge NAME-OF-BRANCH
```
-
diff --git a/doc/incoming_email/README.md b/doc/incoming_email/README.md
index 5a9a1582877..db0f03f2c98 100644
--- a/doc/incoming_email/README.md
+++ b/doc/incoming_email/README.md
@@ -1,302 +1 @@
-# Reply by email
-
-GitLab can be set up to allow users to comment on issues and merge requests by
-replying to notification emails.
-
-## Requirement
-
-Reply by email requires an IMAP-enabled email account. GitLab allows you to use
-three strategies for this feature:
-- using email sub-addressing
-- using a dedicated email address
-- using a catch-all mailbox
-
-### Email sub-addressing
-
-**If your provider or server supports email sub-addressing, we recommend using it.**
-
-[Sub-addressing](https://en.wikipedia.org/wiki/Email_address#Sub-addressing) is
-a feature where any email to `user+some_arbitrary_tag@example.com` will end up
-in the mailbox for `user@example.com`, and is supported by providers such as
-Gmail, Google Apps, Yahoo! Mail, Outlook.com and iCloud, as well as the Postfix
-mail server which you can run on-premises.
-
-### Dedicated email address
-
-This solution is really simple to set up: you just have to create an email
-address dedicated to receive your users' replies to GitLab notifications.
-
-### Catch-all mailbox
-
-A [catch-all mailbox](https://en.wikipedia.org/wiki/Catch-all) for a domain will
-"catch all" the emails addressed to the domain that do not exist in the mail
-server.
-
-## How it works?
-
-### 1. GitLab sends a notification email
-
-When GitLab sends a notification and Reply by email is enabled, the `Reply-To`
-header is set to the address defined in your GitLab configuration, with the
-`%{key}` placeholder (if present) replaced by a specific "reply key". In
-addition, this "reply key" is also added to the `References` header.
-
-### 2. You reply to the notification email
-
-When you reply to the notification email, your email client will:
-
-- send the email to the `Reply-To` address it got from the notification email
-- set the `In-Reply-To` header to the value of the `Message-ID` header from the
- notification email
-- set the `References` header to the value of the `Message-ID` plus the value of
- the notification email's `References` header.
-
-### 3. GitLab receives your reply to the notification email
-
-When GitLab receives your reply, it will look for the "reply key" in the
-following headers, in this order:
-
-1. the `To` header
-1. the `References` header
-
-If it finds a reply key, it will be able to leave your reply as a comment on
-the entity the notification was about (issue, merge request, commit...).
-
-For more details about the `Message-ID`, `In-Reply-To`, and `References headers`,
-please consult [RFC 5322](https://tools.ietf.org/html/rfc5322#section-3.6.4).
-
-## Set it up
-
-If you want to use Gmail / Google Apps with Reply by email, make sure you have
-[IMAP access enabled](https://support.google.com/mail/troubleshooter/1668960?hl=en#ts=1665018)
-and [allowed less secure apps to access the account](https://support.google.com/accounts/answer/6010255).
-
-To set up a basic Postfix mail server with IMAP access on Ubuntu, follow
-[these instructions](./postfix.md).
-
-### Omnibus package installations
-
-1. Find the `incoming_email` section in `/etc/gitlab/gitlab.rb`, enable the
- feature and fill in the details for your specific IMAP server and email account:
-
- ```ruby
- # Configuration for Postfix mail server, assumes mailbox incoming@gitlab.example.com
- gitlab_rails['incoming_email_enabled'] = true
-
- # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
- # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
- gitlab_rails['incoming_email_address'] = "incoming+%{key}@gitlab.example.com"
-
- # Email account username
- # With third party providers, this is usually the full email address.
- # With self-hosted email servers, this is usually the user part of the email address.
- gitlab_rails['incoming_email_email'] = "incoming"
- # Email account password
- gitlab_rails['incoming_email_password'] = "[REDACTED]"
-
- # IMAP server host
- gitlab_rails['incoming_email_host'] = "gitlab.example.com"
- # IMAP server port
- gitlab_rails['incoming_email_port'] = 143
- # Whether the IMAP server uses SSL
- gitlab_rails['incoming_email_ssl'] = false
- # Whether the IMAP server uses StartTLS
- gitlab_rails['incoming_email_start_tls'] = false
-
- # The mailbox where incoming mail will end up. Usually "inbox".
- gitlab_rails['incoming_email_mailbox_name'] = "inbox"
- ```
-
- ```ruby
- # Configuration for Gmail / Google Apps, assumes mailbox gitlab-incoming@gmail.com
- gitlab_rails['incoming_email_enabled'] = true
-
- # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
- # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
- gitlab_rails['incoming_email_address'] = "gitlab-incoming+%{key}@gmail.com"
-
- # Email account username
- # With third party providers, this is usually the full email address.
- # With self-hosted email servers, this is usually the user part of the email address.
- gitlab_rails['incoming_email_email'] = "gitlab-incoming@gmail.com"
- # Email account password
- gitlab_rails['incoming_email_password'] = "[REDACTED]"
-
- # IMAP server host
- gitlab_rails['incoming_email_host'] = "imap.gmail.com"
- # IMAP server port
- gitlab_rails['incoming_email_port'] = 993
- # Whether the IMAP server uses SSL
- gitlab_rails['incoming_email_ssl'] = true
- # Whether the IMAP server uses StartTLS
- gitlab_rails['incoming_email_start_tls'] = false
-
- # The mailbox where incoming mail will end up. Usually "inbox".
- gitlab_rails['incoming_email_mailbox_name'] = "inbox"
- ```
-
-1. Reconfigure GitLab and restart mailroom for the changes to take effect:
-
- ```sh
- sudo gitlab-ctl reconfigure
- sudo gitlab-ctl restart mailroom
- ```
-
-1. Verify that everything is configured correctly:
-
- ```sh
- sudo gitlab-rake gitlab:incoming_email:check
- ```
-
-1. Reply by email should now be working.
-
-### Installations from source
-
-1. Go to the GitLab installation directory:
-
- ```sh
- cd /home/git/gitlab
- ```
-
-1. Find the `incoming_email` section in `config/gitlab.yml`, enable the feature
- and fill in the details for your specific IMAP server and email account:
-
- ```sh
- sudo editor config/gitlab.yml
- ```
-
- ```yaml
- # Configuration for Postfix mail server, assumes mailbox incoming@gitlab.example.com
- incoming_email:
- enabled: true
-
- # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
- # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
- address: "incoming+%{key}@gitlab.example.com"
-
- # Email account username
- # With third party providers, this is usually the full email address.
- # With self-hosted email servers, this is usually the user part of the email address.
- user: "incoming"
- # Email account password
- password: "[REDACTED]"
-
- # IMAP server host
- host: "gitlab.example.com"
- # IMAP server port
- port: 143
- # Whether the IMAP server uses SSL
- ssl: false
- # Whether the IMAP server uses StartTLS
- start_tls: false
-
- # The mailbox where incoming mail will end up. Usually "inbox".
- mailbox: "inbox"
- ```
-
- ```yaml
- # Configuration for Gmail / Google Apps, assumes mailbox gitlab-incoming@gmail.com
- incoming_email:
- enabled: true
-
- # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
- # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
- address: "gitlab-incoming+%{key}@gmail.com"
-
- # Email account username
- # With third party providers, this is usually the full email address.
- # With self-hosted email servers, this is usually the user part of the email address.
- user: "gitlab-incoming@gmail.com"
- # Email account password
- password: "[REDACTED]"
-
- # IMAP server host
- host: "imap.gmail.com"
- # IMAP server port
- port: 993
- # Whether the IMAP server uses SSL
- ssl: true
- # Whether the IMAP server uses StartTLS
- start_tls: false
-
- # The mailbox where incoming mail will end up. Usually "inbox".
- mailbox: "inbox"
- ```
-
-1. Enable `mail_room` in the init script at `/etc/default/gitlab`:
-
- ```sh
- sudo mkdir -p /etc/default
- echo 'mail_room_enabled=true' | sudo tee -a /etc/default/gitlab
- ```
-
-1. Restart GitLab:
-
- ```sh
- sudo service gitlab restart
- ```
-
-1. Verify that everything is configured correctly:
-
- ```sh
- sudo -u git -H bundle exec rake gitlab:incoming_email:check RAILS_ENV=production
- ```
-
-1. Reply by email should now be working.
-
-### Development
-
-1. Go to the GitLab installation directory.
-
-1. Find the `incoming_email` section in `config/gitlab.yml`, enable the feature and fill in the details for your specific IMAP server and email account:
-
- ```yaml
- # Configuration for Gmail / Google Apps, assumes mailbox gitlab-incoming@gmail.com
- incoming_email:
- enabled: true
-
- # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to.
- # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
- address: "gitlab-incoming+%{key}@gmail.com"
-
- # Email account username
- # With third party providers, this is usually the full email address.
- # With self-hosted email servers, this is usually the user part of the email address.
- user: "gitlab-incoming@gmail.com"
- # Email account password
- password: "[REDACTED]"
-
- # IMAP server host
- host: "imap.gmail.com"
- # IMAP server port
- port: 993
- # Whether the IMAP server uses SSL
- ssl: true
- # Whether the IMAP server uses StartTLS
- start_tls: false
-
- # The mailbox where incoming mail will end up. Usually "inbox".
- mailbox: "inbox"
- ```
-
- As mentioned, the part after `+` is ignored, and this will end up in the mailbox for `gitlab-incoming@gmail.com`.
-
-1. Uncomment the `mail_room` line in your `Procfile`:
-
- ```yaml
- mail_room: bundle exec mail_room -q -c config/mail_room.yml
- ```
-
-1. Restart GitLab:
-
- ```sh
- bundle exec foreman start
- ```
-
-1. Verify that everything is configured correctly:
-
- ```sh
- bundle exec rake gitlab:incoming_email:check RAILS_ENV=development
- ```
-
-1. Reply by email should now be working.
+This document was moved to [administration/reply_by_email](../administration/reply_by_email.md).
diff --git a/doc/incoming_email/postfix.md b/doc/incoming_email/postfix.md
index 787d21f7f8f..90833238ac5 100644
--- a/doc/incoming_email/postfix.md
+++ b/doc/incoming_email/postfix.md
@@ -1,321 +1 @@
-# Set up Postfix for Reply by email
-
-This document will take you through the steps of setting up a basic Postfix mail server with IMAP authentication on Ubuntu, to be used with Reply by email.
-
-The instructions make the assumption that you will be using the email address `incoming@gitlab.example.com`, that is, username `incoming` on host `gitlab.example.com`. Don't forget to change it to your actual host when executing the example code snippets.
-
-## Configure your server firewall
-
-1. Open up port 25 on your server so that people can send email into the server over SMTP.
-2. If the mail server is different from the server running GitLab, open up port 143 on your server so that GitLab can read email from the server over IMAP.
-
-## Install packages
-
-1. Install the `postfix` package if it is not installed already:
-
- ```sh
- sudo apt-get install postfix
- ```
-
- When asked about the environment, select 'Internet Site'. When asked to confirm the hostname, make sure it matches `gitlab.example.com`.
-
-1. Install the `mailutils` package.
-
- ```sh
- sudo apt-get install mailutils
- ```
-
-## Create user
-
-1. Create a user for incoming email.
-
- ```sh
- sudo useradd -m -s /bin/bash incoming
- ```
-
-1. Set a password for this user.
-
- ```sh
- sudo passwd incoming
- ```
-
- Be sure not to forget this, you'll need it later.
-
-## Test the out-of-the-box setup
-
-1. Connect to the local SMTP server:
-
- ```sh
- telnet localhost 25
- ```
-
- You should see a prompt like this:
-
- ```sh
- Trying 127.0.0.1...
- Connected to localhost.
- Escape character is '^]'.
- 220 gitlab.example.com ESMTP Postfix (Ubuntu)
- ```
-
- If you get a `Connection refused` error instead, verify that `postfix` is running:
-
- ```sh
- sudo postfix status
- ```
-
- If it is not, start it:
-
- ```sh
- sudo postfix start
- ```
-
-1. Send the new `incoming` user a dummy email to test SMTP, by entering the following into the SMTP prompt:
-
- ```
- ehlo localhost
- mail from: root@localhost
- rcpt to: incoming@localhost
- data
- Subject: Re: Some issue
-
- Sounds good!
- .
- quit
- ```
-
- _**Note:** The `.` is a literal period on its own line._
-
- _**Note:** If you receive an error after entering `rcpt to: incoming@localhost`
- then your Postfix `my_network` configuration is not correct. The error will
- say 'Temporary lookup failure'. See
- [Configure Postfix to receive email from the Internet](#configure-postfix-to-receive-email-from-the-internet)._
-
-1. Check if the `incoming` user received the email:
-
- ```sh
- su - incoming
- mail
- ```
-
- You should see output like this:
-
- ```
- "/var/mail/incoming": 1 message 1 unread
- >U 1 root@localhost 59/2842 Re: Some issue
- ```
-
- Quit the mail app:
-
- ```sh
- q
- ```
-
-1. Log out of the `incoming` account and go back to being `root`:
-
- ```sh
- logout
- ```
-
-## Configure Postfix to use Maildir-style mailboxes
-
-Courier, which we will install later to add IMAP authentication, requires mailboxes to have the Maildir format, rather than mbox.
-
-1. Configure Postfix to use Maildir-style mailboxes:
-
- ```sh
- sudo postconf -e "home_mailbox = Maildir/"
- ```
-
-1. Restart Postfix:
-
- ```sh
- sudo /etc/init.d/postfix restart
- ```
-
-1. Test the new setup:
-
- 1. Follow steps 1 and 2 of _[Test the out-of-the-box setup](#test-the-out-of-the-box-setup)_.
- 1. Check if the `incoming` user received the email:
-
- ```sh
- su - incoming
- MAIL=/home/incoming/Maildir
- mail
- ```
-
- You should see output like this:
-
- ```
- "/home/incoming/Maildir": 1 message 1 unread
- >U 1 root@localhost 59/2842 Re: Some issue
- ```
-
- Quit the mail app:
-
- ```sh
- q
- ```
-
- _**Note:** If `mail` returns an error `Maildir: Is a directory` then your
- version of `mail` doesn't support Maildir style mailboxes. Install
- `heirloom-mailx` by running `sudo apt-get install heirloom-mailx`. Then,
- try the above steps again, substituting `heirloom-mailx` for the `mail`
- command._
-
-1. Log out of the `incoming` account and go back to being `root`:
-
- ```sh
- logout
- ```
-
-## Install the Courier IMAP server
-
-1. Install the `courier-imap` package:
-
- ```sh
- sudo apt-get install courier-imap
- ```
-
-## Configure Postfix to receive email from the internet
-
-1. Let Postfix know about the domains that it should consider local:
-
- ```sh
- sudo postconf -e "mydestination = gitlab.example.com, localhost.localdomain, localhost"
- ```
-
-1. Let Postfix know about the IPs that it should consider part of the LAN:
-
- We'll assume `192.168.1.0/24` is your local LAN. You can safely skip this step if you don't have other machines in the same local network.
-
- ```sh
- sudo postconf -e "mynetworks = 127.0.0.0/8, 192.168.1.0/24"
- ```
-
-1. Configure Postfix to receive mail on all interfaces, which includes the internet:
-
- ```sh
- sudo postconf -e "inet_interfaces = all"
- ```
-
-1. Configure Postfix to use the `+` delimiter for sub-addressing:
-
- ```sh
- sudo postconf -e "recipient_delimiter = +"
- ```
-
-1. Restart Postfix:
-
- ```sh
- sudo service postfix restart
- ```
-
-## Test the final setup
-
-1. Test SMTP under the new setup:
-
- 1. Connect to the SMTP server:
-
- ```sh
- telnet gitlab.example.com 25
- ```
-
- You should see a prompt like this:
-
- ```sh
- Trying 123.123.123.123...
- Connected to gitlab.example.com.
- Escape character is '^]'.
- 220 gitlab.example.com ESMTP Postfix (Ubuntu)
- ```
-
- If you get a `Connection refused` error instead, make sure your firewall is setup to allow inbound traffic on port 25.
-
- 1. Send the `incoming` user a dummy email to test SMTP, by entering the following into the SMTP prompt:
-
- ```
- ehlo gitlab.example.com
- mail from: root@gitlab.example.com
- rcpt to: incoming@gitlab.example.com
- data
- Subject: Re: Some issue
-
- Sounds good!
- .
- quit
- ```
-
- (Note: The `.` is a literal period on its own line)
-
- 1. Check if the `incoming` user received the email:
-
- ```sh
- su - incoming
- MAIL=/home/incoming/Maildir
- mail
- ```
-
- You should see output like this:
-
- ```
- "/home/incoming/Maildir": 1 message 1 unread
- >U 1 root@gitlab.example.com 59/2842 Re: Some issue
- ```
-
- Quit the mail app:
-
- ```sh
- q
- ```
-
- 1. Log out of the `incoming` account and go back to being `root`:
-
- ```sh
- logout
- ```
-
-1. Test IMAP under the new setup:
-
- 1. Connect to the IMAP server:
-
- ```sh
- telnet gitlab.example.com 143
- ```
-
- You should see a prompt like this:
-
- ```sh
- Trying 123.123.123.123...
- Connected to mail.example.gitlab.com.
- Escape character is '^]'.
- - OK [CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE ACL ACL2=UNION] Courier-IMAP ready. Copyright 1998-2011 Double Precision, Inc. See COPYING for distribution information.
- ```
-
- 1. Sign in as the `incoming` user to test IMAP, by entering the following into the IMAP prompt:
-
- ```
- a login incoming PASSWORD
- ```
-
- Replace PASSWORD with the password you set on the `incoming` user earlier.
-
- You should see output like this:
-
- ```
- a OK LOGIN Ok.
- ```
-
- 1. Disconnect from the IMAP server:
-
- ```sh
- a logout
- ```
-
-## Done!
-
-If all the tests were successful, Postfix is all set up and ready to receive email! Continue with the [Reply by email](./README.md) guide to configure GitLab.
-
----------
-
-_This document was adapted from https://help.ubuntu.com/community/PostfixBasicSetupHowto, by contributors to the Ubuntu documentation wiki._
+This document was moved to [administration/reply_by_email_postfix_setup](../administration/reply_by_email_postfix_setup.md).
diff --git a/doc/install/README.md b/doc/install/README.md
index 239f5f301ec..bc831a37735 100644
--- a/doc/install/README.md
+++ b/doc/install/README.md
@@ -1,6 +1,32 @@
# Installation
-- [Installation](installation.md)
-- [Requirements](requirements.md)
-- [Structure](structure.md)
-- [Database MySQL](database_mysql.md)
+GitLab can be installed via various ways. Check the [installation methods][methods]
+for an overview.
+
+## Requirements
+
+Before installing GitLab, make sure to check the [requirements documentation](requirements.md)
+which includes useful information on the supported Operating Systems as well as
+the hardware requirements.
+
+## Installation methods
+
+- [Installation using the Omnibus packages](https://about.gitlab.com/downloads/) -
+ Install GitLab using our official deb/rpm repositories. This is the
+ recommended way.
+- [Installation from source](installation.md) - Install GitLab from source.
+ Useful for unsupported systems like *BSD. For an overview of the directory
+ structure, read the [structure documentation](structure.md).
+- [Docker](https://docs.gitlab.com/omnibus/docker/) - Install GitLab using Docker.
+- [Installing in Kubernetes](kubernetes/index.md) - Install GitLab into a Kubernetes
+ Cluster using our official Helm Chart Repository.
+- Testing only! [DigitalOcean and Docker Machine](digitaloceandocker.md) -
+ Quickly test any version of GitLab on DigitalOcean using Docker Machine.
+
+## Database
+
+While the recommended database is PostgreSQL, we provide information to install
+GitLab using MySQL. Check the [MySQL documentation](database_mysql.md) for more
+information.
+
+[methods]: https://about.gitlab.com/installation/
diff --git a/doc/install/database_mysql.md b/doc/install/database_mysql.md
index e8093f0b257..9a171d34671 100644
--- a/doc/install/database_mysql.md
+++ b/doc/install/database_mysql.md
@@ -1,64 +1,273 @@
# Database MySQL
-## Note
+>**Note:**
+We do not recommend using MySQL due to various issues. For example, case
+[(in)sensitivity](https://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html)
+and [problems](https://bugs.mysql.com/bug.php?id=65830) that
+[suggested](https://bugs.mysql.com/bug.php?id=50909)
+[fixes](https://bugs.mysql.com/bug.php?id=65830) [have](https://bugs.mysql.com/bug.php?id=63164).
-We do not recommend using MySQL due to various issues. For example, case [(in)sensitivity](https://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html) and [problems](https://bugs.mysql.com/bug.php?id=65830) that [suggested](https://bugs.mysql.com/bug.php?id=50909) [fixes](https://bugs.mysql.com/bug.php?id=65830) [have](https://bugs.mysql.com/bug.php?id=63164).
+## Initial database setup
+
+```
+# Install the database packages
+sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev
+
+# Ensure you have MySQL version 5.5.14 or later
+mysql --version
+
+# Pick a MySQL root password (can be anything), type it and press enter
+# Retype the MySQL root password and press enter
+
+# Secure your installation
+sudo mysql_secure_installation
+
+# Login to MySQL
+mysql -u root -p
+
+# Type the MySQL root password
+
+# Create a user for GitLab
+# do not type the 'mysql>', this is part of the prompt
+# change $password in the command below to a real password you pick
+mysql> CREATE USER 'git'@'localhost' IDENTIFIED BY '$password';
+
+# Ensure you can use the InnoDB engine which is necessary to support long indexes
+# If this fails, check your MySQL config files (e.g. `/etc/mysql/*.cnf`, `/etc/mysql/conf.d/*`) for the setting "innodb = off"
+mysql> SET storage_engine=INNODB;
+
+# If you have MySQL < 5.7.7 and want to enable utf8mb4 character set support with your GitLab install, you must set the following NOW:
+mysql> SET GLOBAL innodb_file_per_table=1, innodb_file_format=Barracuda, innodb_large_prefix=1;
+
+# Create the GitLab production database
+mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_general_ci`;
+
+# Grant the GitLab user necessary permissions on the database
+mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES, REFERENCES ON `gitlabhq_production`.* TO 'git'@'localhost';
+
+# Quit the database session
+mysql> \q
+
+# Try connecting to the new database with the new user
+sudo -u git -H mysql -u git -p -D gitlabhq_production
+
+# Type the password you replaced $password with earlier
+
+# You should now see a 'mysql>' prompt
+
+# Quit the database session
+mysql> \q
+```
+
+You are done installing the database for now and can go back to the rest of the installation.
+Please proceed to the rest of the installation before running through the utf8mb4 support section.
+
+### MySQL utf8mb4 support
+
+After installation or upgrade, remember to [convert any new tables](#convert) to `utf8mb4`/`utf8mb4_general_ci`.
+
+---
+
+GitLab 8.14 has introduced [a feature](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7420) requiring `utf8mb4` encoding to be supported in your GitLab MySQL Database, which is not the case if you have setup your database before GitLab 8.16.
+
+Follow the below instructions to ensure you use the most up to date requirements for your GitLab MySQL Database.
+
+**We are about to do the following:**
+- Ensure you can enable `utf8mb4` encoding and `utf8mb4_general_ci` collation for your GitLab DB, tables and data.
+- Convert your GitLab tables and data from `utf8`/`utf8_general_ci` to `utf8mb4`/`utf8mb4_general_ci`
+
+### Check for utf8mb4 support
+
+#### Check for InnoDB File-Per-Table Tablespaces
+
+We need to check, enable and maybe convert your existing GitLab DB tables to the [InnoDB File-Per-Table Tablespaces](http://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) as a prerequise for supporting **utfb8mb4 with long indexes** required by recent GitLab databases.
+
+ # Login to MySQL
+ mysql -u root -p
+
+ # Type the MySQL root password
+ mysql > use gitlabhq_production;
+
+ # Check your MySQL version is >= 5.5.3 (GitLab requires 5.5.14+)
+ mysql > SHOW VARIABLES LIKE 'version';
+ +---------------+-----------------+
+ | Variable_name | Value |
+ +---------------+-----------------+
+ | version | 5.5.53-0+deb8u1 |
+ +---------------+-----------------+
+
+ # Note where is your MySQL data dir for later:
+ mysql > select @@datadir;
+ +----------------+
+ | @@datadir |
+ +----------------+
+ | /var/lib/mysql |
+ +----------------+
+
+ # Note whether your MySQL server runs with innodb_file_per_table ON or OFF:
+ mysql> SELECT @@innodb_file_per_table;
+ +-------------------------+
+ | @@innodb_file_per_table |
+ +-------------------------+
+ | 1 |
+ +-------------------------+
+
+ # You can now quit the database session
+ mysql> \q
+
+> You need **MySQL 5.5.3 or later** to perform this update.
+
+Whatever the results of your checks above, we now need to check if your GitLab database has been created using [InnoDB File-Per-Table Tablespaces](http://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) (i.e. `innodb_file_per_table` was set to **1** at initial setup time).
+
+> Note: This setting is [enabled by default](http://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_file_per_table) since MySQL 5.6.6.
+
+ # Run this command with root privileges, replace the data dir if different:
+ sudo ls -lh /var/lib/mysql/gitlabhq_production/*.ibd | wc -l
+
+ # Run this command with root privileges, replace the data dir if different:
+ sudo ls -lh /var/lib/mysql/gitlabhq_production/*.frm | wc -l
-## MySQL
- # Install the database packages
- sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev
+- **Case 1: a result > 0 for both commands**
- # Ensure you have MySQL version 5.5.14 or later
- mysql --version
+Congrats, your GitLab database uses the right InnoDB tablespace format.
- # Pick a MySQL root password (can be anything), type it and press enter
- # Retype the MySQL root password and press enter
+However, you must still ensure that any **future tables** created by GitLab will still use the right format:
- # Secure your installation
- sudo mysql_secure_installation
+- If `SELECT @@innodb_file_per_table` returned **1** previously, your server is running correctly.
+> It's however a requirement to check *now* that this setting is indeed persisted in your [my.cnf](https://dev.mysql.com/doc/refman/5.7/en/tablespace-enabling.html) file!
+
+- If `SELECT @@innodb_file_per_table` returned **0** previously, your server is not running correctly.
+> [Enable innodb_file_per_table](https://dev.mysql.com/doc/refman/5.7/en/tablespace-enabling.html) by running in a MySQL session as root the command `SET GLOBAL innodb_file_per_table=1, innodb_file_format=Barracuda;` and persist the two settings in your [my.cnf](https://dev.mysql.com/doc/refman/5.7/en/tablespace-enabling.html) file
+
+Now, if you have a **different result** returned by the 2 commands above, it means you have a **mix of tables format** uses in your GitLab database. This can happen if your MySQL server had different values for `innodb_file_per_table` in its life and you updated GitLab at different moments with those inconsistent values. So keep reading.
+
+- **Case 2: a result equals to "0" OR not the same result for both commands**
+
+Unfortunately, none or only some of your GitLab database tables use the GitLab requirement of [InnoDB File-Per-Table Tablespaces](http://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html).
+
+Let's enable what we need on the running server:
# Login to MySQL
mysql -u root -p
# Type the MySQL root password
- # Create a user for GitLab
- # do not type the 'mysql>', this is part of the prompt
- # change $password in the command below to a real password you pick
- mysql> CREATE USER 'git'@'localhost' IDENTIFIED BY '$password';
+ # Enable innodb_file_per_table and set innodb_file_format on the running server:
+ mysql > SET GLOBAL innodb_file_per_table=1, innodb_file_format=Barracuda;
+
+ # You can now quit the database session
+ mysql> \q
+
+> Now, **persist** [innodb_file_per_table](https://dev.mysql.com/doc/refman/5.6/en/tablespace-enabling.html) and [innodb_file_format](https://dev.mysql.com/doc/refman/5.6/en/innodb-file-format-enabling.html) in your `my.cnf` file.
+
+Ensure at this stage that your GitLab instance is indeed **stopped**.
+
+Now, let's convert all the GitLab database tables to the new tablespace format:
+
+ # Login to MySQL
+ mysql -u root -p
+
+ # Type the MySQL root password
+ mysql > use gitlabhq_production;
- # Ensure you can use the InnoDB engine which is necessary to support long indexes
- # If this fails, check your MySQL config files (e.g. `/etc/mysql/*.cnf`, `/etc/mysql/conf.d/*`) for the setting "innodb = off"
- mysql> SET storage_engine=INNODB;
+ # Safety check: you should still have those values set as follow:
+ mysql> SELECT @@innodb_file_per_table, @@innodb_file_format;
+ +-------------------------+----------------------+
+ | @@innodb_file_per_table | @@innodb_file_format |
+ +-------------------------+----------------------+
+ | 1 | Barracuda |
+ +-------------------------+----------------------+
- # Create the GitLab production database
- mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
+ mysql > SELECT CONCAT('ALTER TABLE `', TABLE_NAME,'` ENGINE=InnoDB;') AS 'Copy & run these SQL statements:' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="gitlabhq_production" AND TABLE_TYPE="BASE TABLE";
- # Grant the GitLab user necessary permissions on the database
- mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES, REFERENCES ON `gitlabhq_production`.* TO 'git'@'localhost';
+ # If previous query returned results, copy & run all shown SQL statements
- # Quit the database session
+ # You can now quit the database session
mysql> \q
- # Try connecting to the new database with the new user
- sudo -u git -H mysql -u git -p -D gitlabhq_production
+---
+
+#### Check for proper InnoDB File Format, Row Format, Large Prefix and tables conversion
+
+We need to check, enable and probably convert your existing GitLab DB tables to use the [Barracuda InnoDB file format](https://dev.mysql.com/doc/refman/5.6/en/innodb-file-format.html), the [DYNAMIC row format](https://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_dynamic_row_format) and [innodb_large_prefix](http://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_large_prefix) as a second prerequisite for supporting **utfb8mb4 with long indexes** used by recent GitLab databases.
+
+ # Login to MySQL
+ mysql -u root -p
+
+ # Type the MySQL root password
+ mysql > use gitlabhq_production;
- # Type the password you replaced $password with earlier
+ # Set innodb_file_format and innodb_large_prefix on the running server:
+ # Note: These are the default settings only for MySQL 5.7.7 and later.
- # You should now see a 'mysql>' prompt
+ mysql > SET GLOBAL innodb_file_format=Barracuda, innodb_large_prefix=1;
- # Quit the database session
+ # Your DB must be (still) using utf8/utf8_general_ci as default encoding and collation.
+ # We will NOT change the default encoding and collation on the DB in order to support future GitLab migrations creating tables
+ # that require "long indexes support" on installations using MySQL <= 5.7.9.
+ # However, when such migrations occur, you will have to follow this guide again to convert the newly created tables to the proper encoding/collation.
+
+ # This should return the following:
+ mysql> SELECT @@character_set_database, @@collation_database;
+ +--------------------------+----------------------+
+ | @@character_set_database | @@collation_database |
+ +--------------------------+----------------------+
+ | utf8 | utf8_general_ci |
+ +--------------------------+----------------------+
+
+> Now, ensure that [innodb_file_format](https://dev.mysql.com/doc/refman/5.6/en/tablespace-enabling.html) and [innodb_large_prefix](http://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_large_prefix) are **persisted** in your `my.cnf` file.
+
+#### Tables and data conversion to utf8mb4
+<a name="convert"></a>
+
+Now that you have a persistent MySQL setup, you can safely upgrade tables after setup or upgrade time:
+
+ # Convert tables not using ROW_FORMAT DYNAMIC:
+
+ mysql> SELECT CONCAT('ALTER TABLE `', TABLE_NAME,'` ROW_FORMAT=DYNAMIC;') AS 'Copy & run these SQL statements:' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="gitlabhq_production" AND TABLE_TYPE="BASE TABLE" AND ROW_FORMAT!="Dynamic";
+
+ # !! If previous query returned results, copy & run all shown SQL statements
+
+ # Convert tables/columns not using utf8mb4/utf8mb4_general_ci as encoding/collation:
+
+ mysql > SET foreign_key_checks = 0;
+
+ mysql > SELECT CONCAT('ALTER TABLE `', TABLE_NAME,'` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;') AS 'Copy & run these SQL statements:' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="gitlabhq_production" AND TABLE_COLLATION != "utf8mb4_general_ci" AND TABLE_TYPE="BASE TABLE";
+
+ # !! If previous query returned results, copy & run all shown SQL statements
+
+ # Turn foreign key checks back on
+ mysql > SET foreign_key_checks = 1;
+
+ # You can now quit the database session
mysql> \q
- # You are done installing the database and can go back to the rest of the installation.
+Ensure your GitLab database configuration file uses a proper connection encoding and collation:
+
+```sudo -u git -H editor config/database.yml```
+
+ production:
+ adapter: mysql2
+ encoding: utf8mb4
+ collation: utf8mb4_general_ci
+
+[Restart your GitLab instance](../administration/restart_gitlab.md).
+
## MySQL strings limits
After installation or upgrade, remember to run the `add_limits_mysql` Rake task:
+**Omnibus GitLab installations**
+```
+sudo gitlab-rake add_limits_mysql
+```
+
+**Installations from source**
+
```
-bundle exec rake add_limits_mysql
+bundle exec rake add_limits_mysql RAILS_ENV=production
```
The `text` type in MySQL has a different size limit than the `text` type in
@@ -72,5 +281,5 @@ GitLab database to `longtext` columns, which can persist values of up to 4GB
Details can be found in the [PostgreSQL][postgres-text-type] and
[MySQL][mysql-text-types] manuals.
-[postgres-text-type]: http://www.postgresql.org/docs/9.1/static/datatype-character.html
+[postgres-text-type]: http://www.postgresql.org/docs/9.2/static/datatype-character.html
[mysql-text-types]: http://dev.mysql.com/doc/refman/5.7/en/string-type-overview.html
diff --git a/doc/install/digitaloceandocker.md b/doc/install/digitaloceandocker.md
new file mode 100644
index 00000000000..8efc0530b8a
--- /dev/null
+++ b/doc/install/digitaloceandocker.md
@@ -0,0 +1,139 @@
+# Digital Ocean and Docker Machine test environment
+
+## Warning. This guide is for quickly testing different versions of GitLab and
+## not recommended for ease of future upgrades or keeping the data you create.
+
+## Initial setup
+
+In this guide you'll configure a Digital Ocean droplet and set up Docker
+locally on either macOS or Linux.
+
+### On macOS
+
+#### Install Docker Toolbox
+
+1. [https://www.docker.com/products/docker-toolbox](https://www.docker.com/products/docker-toolbox)
+
+### On Linux
+
+#### Install Docker Engine
+
+1. [https://docs.docker.com/engine/installation/linux](https://docs.docker.com/engine/installation/linux/)
+
+#### Install Docker Machine
+
+1. [https://docs.docker.com/machine/install-machine](https://docs.docker.com/machine/install-machine/)
+
+_The rest of the steps are identical for macOS and Linux_
+
+### Create new docker host
+
+1. Login to Digital Ocean
+1. Generate a new API token at https://cloud.digitalocean.com/settings/api/tokens
+
+
+This command will create a new DO droplet called `gitlab-test-env-do` that will act as a docker host.
+
+**Note: 4GB is the minimum requirement for a Docker host that will run more then one GitLab instance**
+
++ RAM: 4GB
++ Name: `gitlab-test-env-do`
++ Driver: `digitalocean`
+
+
+**Set the DO token** - Replace the string below with your generated token
+
+```
+export DOTOKEN=cf3dfd0662933203005c4a73396214b7879d70aabc6352573fe178d340a80248
+```
+
+**Create the machine**
+
+```
+docker-machine create \
+ --driver digitalocean \
+ --digitalocean-access-token=$DOTOKEN \
+ --digitalocean-size "4gb" \
+ gitlab-test-env-do
+```
+
++ Resource: https://docs.docker.com/machine/drivers/digital-ocean/
+
+
+### Creating GitLab test instance
+
+
+#### Connect your shell to the new machine
+
+
+In this example we'll create a GitLab EE 8.10.8 instance.
+
+
+First connect the docker client to the docker host you created previously.
+
+```
+eval "$(docker-machine env gitlab-test-env-do)"
+```
+
+You can add this to your `~/.bash_profile` file to ensure the `docker` client uses the `gitlab-test-env-do` docker host
+
+
+#### Create new GitLab container
+
++ HTTP port: `8888`
++ SSH port: `2222`
+ + Set `gitlab_shell_ssh_port` using `--env GITLAB_OMNIBUS_CONFIG `
++ Hostname: IP of docker host
++ Container name: `gitlab-test-8.10`
++ GitLab version: **EE** `8.10.8-ee.0`
+
+##### Setup container settings
+
+```
+export SSH_PORT=2222
+export HTTP_PORT=8888
+export VERSION=8.10.8-ee.0
+export NAME=gitlab-test-8.10
+```
+
+##### Create container
+```
+docker run --detach \
+--env GITLAB_OMNIBUS_CONFIG="external_url 'http://$(docker-machine ip gitlab-test-env-do):$HTTP_PORT'; gitlab_rails['gitlab_shell_ssh_port'] = $SSH_PORT;" \
+--hostname $(docker-machine ip gitlab-test-env-do) \
+-p $HTTP_PORT:$HTTP_PORT -p $SSH_PORT:22 \
+--name $NAME \
+gitlab/gitlab-ee:$VERSION
+```
+
+#### Connect to the GitLab container
+
+##### Retrieve the docker host IP
+
+```
+docker-machine ip gitlab-test-env-do
+# example output: 192.168.151.134
+```
+
+
++ Browse to: http://192.168.151.134:8888/
+
+
+##### Execute interactive shell/edit configuration
+
+
+```
+docker exec -it $NAME /bin/bash
+```
+
+```
+# example commands
+root@192:/# vi /etc/gitlab/gitlab.rb
+root@192:/# gitlab-ctl reconfigure
+```
+
+#### Resources
+
++ [https://docs.gitlab.com/omnibus/docker/](https://docs.gitlab.com/omnibus/docker/)
++ [https://docs.docker.com/machine/get-started/](https://docs.docker.com/machine/get-started/)
++ [https://docs.docker.com/machine/reference/ip/](https://docs.docker.com/machine/reference/ip/)+
diff --git a/doc/install/google-protobuf.md b/doc/install/google-protobuf.md
new file mode 100644
index 00000000000..a531b4519b3
--- /dev/null
+++ b/doc/install/google-protobuf.md
@@ -0,0 +1,26 @@
+# Installing a locally compiled google-protobuf gem
+
+First we must find the exact version of google-protobuf that your
+GitLab installation requires.
+
+ cd /home/git/gitlab
+
+ # Only one of the following two commands will print something. It
+ # will look like: * google-protobuf (3.2.0)
+ bundle list | grep google-protobuf
+ bundle check | grep google-protobuf
+
+Below we use `3.2.0` as an example. Replace it with the version number
+you found above.
+
+ cd /home/git/gitlab
+ sudo -u git -H gem install google-protobuf --version 3.2.0 --platform ruby
+
+Finally, you can test whether google-protobuf loads correctly. The
+following should print 'OK'.
+
+ sudo -u git -H bundle exec ruby -rgoogle/protobuf -e 'puts :OK'
+
+If the `gem install` command fails you may need to install developer
+tools. On Debian: `apt-get install build-essential libgmp-dev`, on
+Centos/RedHat `yum groupinstall 'Development Tools'`.
diff --git a/doc/install/google_cloud_platform/img/change_admin_passwd_email.png b/doc/install/google_cloud_platform/img/change_admin_passwd_email.png
new file mode 100644
index 00000000000..1ffe14f60ff
--- /dev/null
+++ b/doc/install/google_cloud_platform/img/change_admin_passwd_email.png
Binary files differ
diff --git a/doc/install/google_cloud_platform/img/chrome_not_secure_page.png b/doc/install/google_cloud_platform/img/chrome_not_secure_page.png
new file mode 100644
index 00000000000..e732066908f
--- /dev/null
+++ b/doc/install/google_cloud_platform/img/chrome_not_secure_page.png
Binary files differ
diff --git a/doc/install/google_cloud_platform/img/gcp_gitlab_being_deployed.png b/doc/install/google_cloud_platform/img/gcp_gitlab_being_deployed.png
new file mode 100644
index 00000000000..2a1859da6e3
--- /dev/null
+++ b/doc/install/google_cloud_platform/img/gcp_gitlab_being_deployed.png
Binary files differ
diff --git a/doc/install/google_cloud_platform/img/gcp_gitlab_overview.png b/doc/install/google_cloud_platform/img/gcp_gitlab_overview.png
new file mode 100644
index 00000000000..1c4c870dbc9
--- /dev/null
+++ b/doc/install/google_cloud_platform/img/gcp_gitlab_overview.png
Binary files differ
diff --git a/doc/install/google_cloud_platform/img/gcp_landing.png b/doc/install/google_cloud_platform/img/gcp_landing.png
new file mode 100644
index 00000000000..6398d247ba0
--- /dev/null
+++ b/doc/install/google_cloud_platform/img/gcp_landing.png
Binary files differ
diff --git a/doc/install/google_cloud_platform/img/gcp_launcher_console_home_page.png b/doc/install/google_cloud_platform/img/gcp_launcher_console_home_page.png
new file mode 100644
index 00000000000..f492888ea4a
--- /dev/null
+++ b/doc/install/google_cloud_platform/img/gcp_launcher_console_home_page.png
Binary files differ
diff --git a/doc/install/google_cloud_platform/img/gcp_search_for_gitlab.png b/doc/install/google_cloud_platform/img/gcp_search_for_gitlab.png
new file mode 100644
index 00000000000..b38af3966e2
--- /dev/null
+++ b/doc/install/google_cloud_platform/img/gcp_search_for_gitlab.png
Binary files differ
diff --git a/doc/install/google_cloud_platform/img/gitlab_deployed_page.png b/doc/install/google_cloud_platform/img/gitlab_deployed_page.png
new file mode 100644
index 00000000000..fef9ae45f32
--- /dev/null
+++ b/doc/install/google_cloud_platform/img/gitlab_deployed_page.png
Binary files differ
diff --git a/doc/install/google_cloud_platform/img/gitlab_first_sign_in.png b/doc/install/google_cloud_platform/img/gitlab_first_sign_in.png
new file mode 100644
index 00000000000..381c0fe48a5
--- /dev/null
+++ b/doc/install/google_cloud_platform/img/gitlab_first_sign_in.png
Binary files differ
diff --git a/doc/install/google_cloud_platform/img/gitlab_launch_button.png b/doc/install/google_cloud_platform/img/gitlab_launch_button.png
new file mode 100644
index 00000000000..50f66f66118
--- /dev/null
+++ b/doc/install/google_cloud_platform/img/gitlab_launch_button.png
Binary files differ
diff --git a/doc/install/google_cloud_platform/img/new_gitlab_deployment_settings.png b/doc/install/google_cloud_platform/img/new_gitlab_deployment_settings.png
new file mode 100644
index 00000000000..00060841619
--- /dev/null
+++ b/doc/install/google_cloud_platform/img/new_gitlab_deployment_settings.png
Binary files differ
diff --git a/doc/install/google_cloud_platform/img/ssh_via_button.png b/doc/install/google_cloud_platform/img/ssh_via_button.png
new file mode 100644
index 00000000000..26106f159ad
--- /dev/null
+++ b/doc/install/google_cloud_platform/img/ssh_via_button.png
Binary files differ
diff --git a/doc/install/google_cloud_platform/index.md b/doc/install/google_cloud_platform/index.md
new file mode 100644
index 00000000000..35220119e9b
--- /dev/null
+++ b/doc/install/google_cloud_platform/index.md
@@ -0,0 +1,172 @@
+# Installing GitLab on Google Cloud Platform
+
+![GCP landing page](img/gcp_landing.png)
+
+>**Important note:**
+GitLab has no official images in Google Cloud Platform yet. This guide serves
+as a template for when the GitLab VM will be available.
+
+The fastest way to get started on [Google Cloud Platform (GCP)][gcp] is through
+the [Google Cloud Launcher][launcher] program.
+
+## Prerequisites
+
+There are only two prerequisites in order to install GitLab on GCP:
+
+1. You need to have a Google account.
+1. You need to sign up for the GCP program. If this is your first time, Google
+ gives you [$300 credit for free][freetrial] to consume over a 60-day period.
+
+Once you have performed those two steps, you can visit the
+[GCP launcher console][console] which has a list of all the things you can
+deploy on GCP.
+
+![GCP launcher console](img/gcp_launcher_console_home_page.png)
+
+The next step is to find and install GitLab.
+
+## Configuring and deploying the VM
+
+To deploy GitLab on GCP you need to follow five simple steps:
+
+1. Go to https://cloud.google.com/launcher and login with your Google credentials
+1. Search for GitLab from GitLab Inc. (not the same as Bitnami) and click on
+ the tile.
+
+ ![Search for GitLab](img/gcp_search_for_gitlab.png)
+
+1. In the next page, you can see an overview of the GitLab VM as well as some
+ estimated costs. Click the **Launch on Compute Engine** button to choose the
+ hardware and network settings.
+
+ ![Launch on Compute Engine](img/gcp_gitlab_overview.png)
+
+1. In the settings page you can choose things like the datacenter where your GitLab
+ server will be hosted, the number of CPUs and amount of RAM, the disk size
+ and type, etc. Read GitLab's [requirements documentation][req] for more
+ details on what to choose depending on your needs.
+
+ ![Deploy settings](img/new_gitlab_deployment_settings.png)
+
+1. As a last step, hit **Deploy** when ready. The process will finish in a few
+ seconds.
+
+ ![Deploy in progress](img/gcp_gitlab_being_deployed.png)
+
+
+## Visiting GitLab for the first time
+
+After a few seconds, GitLab will be successfully deployed and you should be
+able to see the IP address that Google assigned to the VM, as well as the
+credentials to the GitLab admin account.
+
+![Deploy settings](img/gitlab_deployed_page.png)
+
+1. Click on the IP under **Site address** to visit GitLab.
+1. Accept the self-signed certificate that Google automatically deployed in
+ order to securely reach GitLab's login page.
+1. Use the username and password that are present in the Google console page
+ to login into GitLab and click **Sign in**.
+
+ ![GitLab first sign in](img/gitlab_first_sign_in.png)
+
+Congratulations! GitLab is now installed and you can access it via your browser,
+but we're not done yet. There are some steps you need to take in order to have
+a fully functional GitLab installation.
+
+## Next steps
+
+These are the most important next steps to take after you installed GitLab for
+the first time.
+
+### Changing the admin password and email
+
+Google assigned a random password for the GitLab admin account and you should
+change it ASAP:
+
+1. Visit the GitLab admin page through the link in the Google console under
+ **Admin URL**.
+1. Find the Administrator user under the **Users** page and hit **Edit**.
+1. Change the email address to a real one and enter a new password.
+
+ ![Change GitLab admin password](img/change_admin_passwd_email.png)
+
+1. Hit **Save changes** for the changes to take effect.
+1. After changing the password, you will be signed out from GitLab. Use the
+ new credentials to login again.
+
+### Assigning a static IP
+
+By default, Google assigns an ephemeral IP to your instance. It is strongly
+recommended to assign a static IP if you are going to use GitLab in production
+and use a domain name as we'll see below.
+
+Read Google's documentation on how to [promote an ephemeral IP address][ip].
+
+### Using a domain name
+
+Assuming you have a domain name in your possession and you have correctly
+set up DNS to point to the static IP you configured in the previous step,
+here's how you configure GitLab to be aware of the change:
+
+1. SSH into the VM. You can easily use the **SSH** button in the Google console
+ and a new window will pop up.
+
+ ![SSH button](img/ssh_via_button.png)
+
+ In the future you might want to set up [connecting with an SSH key][ssh]
+ instead.
+
+1. Edit the config file of Omnibus GitLab using your favorite text editor:
+
+ ```
+ sudo vim /etc/gitlab/gitlab.rb
+ ```
+
+1. Set the `external_url` value to the domain name you wish GitLab to have
+ **without** `https`:
+
+ ```
+ external_url 'http://gitlab.example.com'
+ ```
+
+ We will set up HTTPS in the next step, no need to do this now.
+
+1. Reconfigure GitLab for the changes to take effect:
+
+ ```
+ sudo gitlab-ctl reconfigure
+ ```
+
+1. You can now visit GitLab using the domain name.
+
+### Configuring HTTPS with the domain name
+
+Although not needed, it's strongly recommended to secure GitLab with a TLS
+certificate. Follow the steps in the [Omnibus documentation][omni-ssl].
+
+### Configuring the email SMTP settings
+
+You need to configure the email SMTP settings correctly otherwise GitLab will
+not be able to send notification emails, like comments, and password changes.
+Check the [Omnibus documentation][omni-smtp] how to do so.
+
+## Further reading
+
+GitLab can be configured to authenticate with other OAuth providers, LDAP, SAML,
+Kerberos, etc. Here are some documents you might be interested in reading:
+
+- [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/)
+- [Integration documentation](https://docs.gitlab.com/ce/integration/)
+- [GitLab Pages configuration](https://docs.gitlab.com/ce/administration/pages/index.html)
+- [GitLab Container Registry configuration](https://docs.gitlab.com/ce/administration/container_registry.html)
+
+[console]: https://console.cloud.google.com/launcher "GCP launcher console"
+[freetrial]: https://console.cloud.google.com/freetrial "GCP free trial"
+[ip]: https://cloud.google.com/compute/docs/configure-instance-ip-addresses#promote_ephemeral_ip "Configuring an Instance's IP Addresses"
+[gcp]: https://cloud.google.com/ "Google Cloud Platform"
+[launcher]: https://cloud.google.com/launcher/ "Google Cloud Launcher home page"
+[req]: ../requirements.md "GitLab hardware and software requirements"
+[ssh]: https://cloud.google.com/compute/docs/instances/connecting-to-instance "Connecting to Linux Instances"
+[omni-smtp]: https://docs.gitlab.com/omnibus/settings/smtp.html#smtp-settings "Omnibus GitLab SMTP settings"
+[omni-ssl]: https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https "Omnibus GitLab enable HTTPS"
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 378ab6857b8..84af6432889 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -39,6 +39,7 @@ The GitLab installation consists of setting up the following components:
1. Packages / Dependencies
1. Ruby
1. Go
+1. Node
1. System Users
1. Database
1. Redis
@@ -63,7 +64,7 @@ up-to-date and install it.
Install the required packages (needed to compile Ruby and native extensions to Ruby gems):
- sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate python-docutils pkg-config cmake nodejs
+ sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate python-docutils pkg-config cmake
If you want to use Kerberos for user authentication, then install libkrb5-dev:
@@ -76,7 +77,7 @@ Make sure you have the right version of Git installed
# Install Git
sudo apt-get install -y git-core
- # Make sure Git is version 2.7.4 or higher
+ # Make sure Git is version 2.8.4 or higher
git --version
Is the system packaged Git too old? Remove it and compile from source.
@@ -89,9 +90,9 @@ Is the system packaged Git too old? Remove it and compile from source.
# Download and compile from source
cd /tmp
- curl --remote-name --progress https://www.kernel.org/pub/software/scm/git/git-2.7.4.tar.gz
- echo '7104c4f5d948a75b499a954524cb281fe30c6649d8abe20982936f75ec1f275b git-2.7.4.tar.gz' | shasum -a256 -c - && tar -xzf git-2.7.4.tar.gz
- cd git-2.7.4/
+ curl --remote-name --progress https://www.kernel.org/pub/software/scm/git/git-2.8.4.tar.gz
+ echo '626e319f8a24fc0866167ea5f6bf3e2f38f69d6cb2e59e150f13709ca3ebf301 git-2.8.4.tar.gz' | shasum -a256 -c - && tar -xzf git-2.8.4.tar.gz
+ cd git-2.8.4/
./configure
make prefix=/usr/local all
@@ -108,13 +109,19 @@ Then select 'Internet Site' and press enter to confirm the hostname.
## 2. Ruby
-**Note:** The current supported Ruby versions are 2.1.x and 2.3.x. 2.3.x is preferred, and support for 2.1.x will be dropped in the future.
+The Ruby interpreter is required to run GitLab.
+
+**Note:** The current supported Ruby (MRI) version is 2.3.x. GitLab 9.0 dropped
+support for Ruby 2.1.x.
The use of Ruby version managers such as [RVM], [rbenv] or [chruby] with GitLab
in production, frequently leads to hard to diagnose problems. For example,
GitLab Shell is called from OpenSSH, and having a version manager can prevent
pushing and pulling over SSH. Version managers are not supported and we strongly
-advise everyone to follow the instructions below to use a system Ruby.
+advise everyone to follow the instructions below to use a system Ruby.
+
+Linux distributions generally have older versions of Ruby available, so these
+instructions are designed to install Ruby from the official source code.
Remove the old Ruby 1.8 if present:
@@ -123,43 +130,62 @@ Remove the old Ruby 1.8 if present:
Download Ruby and compile it:
mkdir /tmp/ruby && cd /tmp/ruby
- curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz
- echo 'c39b4001f7acb4e334cb60a0f4df72d434bef711 ruby-2.3.1.tar.gz' | shasum -c - && tar xzf ruby-2.3.1.tar.gz
- cd ruby-2.3.1
+ curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
+ echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
+ cd ruby-2.3.3
./configure --disable-install-rdoc
make
sudo make install
-Install the Bundler Gem:
+Then install the Bundler Gem:
sudo gem install bundler --no-ri --no-rdoc
## 3. Go
-Since GitLab 8.0, Git HTTP requests are handled by gitlab-workhorse (formerly
-gitlab-git-http-server). This is a small daemon written in Go. To install
-gitlab-workhorse we need a Go compiler. The instructions below assume you
-use 64-bit Linux. You can find downloads for other platforms at the [Go download
+Since GitLab 8.0, GitLab has several daemons written in Go. To install
+GitLab we need a Go compiler. The instructions below assume you use 64-bit
+Linux. You can find downloads for other platforms at the [Go download
page](https://golang.org/dl).
- curl --remote-name --progress https://storage.googleapis.com/golang/go1.5.3.linux-amd64.tar.gz
- echo '43afe0c5017e502630b1aea4d44b8a7f059bf60d7f29dfd58db454d4e4e0ae53 go1.5.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.5.3.linux-amd64.tar.gz
+ # Remove former Go installation folder
+ sudo rm -rf /usr/local/go
+
+ curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
+ echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
+ sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
- rm go1.5.3.linux-amd64.tar.gz
+ rm go1.8.3.linux-amd64.tar.gz
+
+## 4. Node
+
+Since GitLab 8.17, GitLab requires the use of node >= v4.3.0 to compile
+javascript assets, and yarn >= v0.17.0 to manage javascript dependencies.
+In many distros the versions provided by the official package repositories
+are out of date, so we'll need to install through the following commands:
-## 4. System Users
+ # install node v7.x
+ curl --location https://deb.nodesource.com/setup_7.x | sudo bash -
+ sudo apt-get install -y nodejs
+
+ # install yarn
+ curl --location https://yarnpkg.com/install.sh | bash -
+
+Visit the official websites for [node](https://nodejs.org/en/download/package-manager/) and [yarn](https://yarnpkg.com/en/docs/install/) if you have any trouble with these steps.
+
+## 5. System Users
Create a `git` user for GitLab:
sudo adduser --disabled-login --gecos 'GitLab' git
-## 5. Database
+## 6. Database
We recommend using a PostgreSQL database. For MySQL check the
[MySQL setup guide](database_mysql.md).
-> **Note**: because we need to make use of extensions you need at least pgsql 9.1.
+> **Note**: because we need to make use of extensions and concurrent index removal,
+you need at least PostgreSQL 9.2.
1. Install the database packages:
@@ -173,16 +199,16 @@ We recommend using a PostgreSQL database. For MySQL check the
sudo -u postgres psql -d template1 -c "CREATE USER git CREATEDB;"
```
-1. Create the GitLab production database and grant all privileges on database:
+1. Create the `pg_trgm` extension (required for GitLab 8.6+):
```bash
- sudo -u postgres psql -d template1 -c "CREATE DATABASE gitlabhq_production OWNER git;"
+ sudo -u postgres psql -d template1 -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
```
-1. Create the `pg_trgm` extension (required for GitLab 8.6+):
+1. Create the GitLab production database and grant all privileges on database:
```bash
- sudo -u postgres psql -d template1 -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
+ sudo -u postgres psql -d template1 -c "CREATE DATABASE gitlabhq_production OWNER git;"
```
1. Try connecting to the new database with the new user:
@@ -215,7 +241,7 @@ We recommend using a PostgreSQL database. For MySQL check the
gitlabhq_production> \q
```
-## 6. Redis
+## 7. Redis
GitLab requires at least Redis 2.8.
@@ -260,7 +286,7 @@ sudo service redis-server restart
sudo usermod -aG redis git
```
-## 7. GitLab
+## 8. GitLab
# We'll install GitLab into home directory of the user "git"
cd /home/git
@@ -268,9 +294,9 @@ sudo usermod -aG redis git
### Clone the Source
# Clone GitLab repository
- sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-13-stable gitlab
+ sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 9-2-stable gitlab
-**Note:** You can change `8-13-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
+**Note:** You can change `9-2-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It
@@ -304,12 +330,15 @@ sudo usermod -aG redis git
# now that files in public/uploads are served by gitlab-workhorse
sudo chmod 0700 public/uploads
- # Change the permissions of the directory where CI build traces are stored
+ # Change the permissions of the directory where CI job traces are stored
sudo chmod -R u+rwX builds/
# Change the permissions of the directory where CI artifacts are stored
sudo chmod -R u+rwX shared/artifacts/
+ # Change the permissions of the directory where GitLab Pages are stored
+ sudo chmod -R ug+rwX shared/pages/
+
# Copy the example Unicorn config
sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb
@@ -393,21 +422,18 @@ GitLab Shell is an SSH access and repository management software developed speci
### Install gitlab-workhorse
-GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
+GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/). The
+following command-line will install GitLab-Workhorse in `/home/git/gitlab-workhorse`
+which is the recommended location.
- cd /home/git
- sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git
- cd gitlab-workhorse
- sudo -u git -H git checkout v0.8.4
- sudo -u git -H make
+ sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production
-### Initialize Database and Activate Advanced Features
+You can specify a different Git repository by providing it as an extra paramter:
- # Go to GitLab installation folder
+ sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse,https://example.com/gitlab-workhorse.git]" RAILS_ENV=production
- cd /home/git/gitlab
+
+### Initialize Database and Activate Advanced Features
sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
@@ -441,6 +467,28 @@ Make GitLab start on boot:
sudo update-rc.d gitlab defaults 21
+### Install Gitaly
+
+ # Fetch Gitaly source with Git and compile with Go
+ sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly]" RAILS_ENV=production
+
+You can specify a different Git repository by providing it as an extra paramter:
+
+ sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly,https://example.com/gitaly.git]" RAILS_ENV=production
+
+Next, make sure gitaly configured:
+
+ # Restrict Gitaly socket access
+ sudo chmod 0700 /home/git/gitlab/tmp/sockets/private
+ sudo chown git /home/git/gitlab/tmp/sockets/private
+
+ # If you are using non-default settings you need to update config.toml
+ cd /home/git/gitaly
+ sudo -u git -H editor config.toml
+
+For more information about configuring Gitaly see
+[doc/administration/gitaly](../administration/gitaly).
+
### Setup Logrotate
sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
@@ -453,7 +501,12 @@ Check if GitLab and its environment are configured correctly:
### Compile Assets
- sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
+ sudo -u git -H yarn install --production --pure-lockfile
+ sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
+
+### Compile GetText PO files
+
+ sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
### Start Your GitLab Instance
@@ -461,7 +514,7 @@ Check if GitLab and its environment are configured correctly:
# or
sudo /etc/init.d/gitlab restart
-## 8. Nginx
+## 9. Nginx
**Note:** Nginx is the officially supported web server for GitLab. If you cannot or do not want to use Nginx as your web server, have a look at the [GitLab recipes](https://gitlab.com/gitlab-org/gitlab-recipes/).
@@ -476,15 +529,23 @@ Copy the example site config:
sudo cp lib/support/nginx/gitlab /etc/nginx/sites-available/gitlab
sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab
-Make sure to edit the config file to match your setup:
+Make sure to edit the config file to match your setup. Also, ensure that you match your paths to GitLab, especially if installing for a user other than the 'git' user:
# Change YOUR_SERVER_FQDN to the fully-qualified
# domain name of your host serving GitLab.
+ #
+ # Remember to match your paths to GitLab, especially
+ # if installing for a user other than 'git'.
+ #
# If using Ubuntu default nginx install:
# either remove the default_server from the listen line
# or else sudo rm -f /etc/nginx/sites-enabled/default
sudo editor /etc/nginx/sites-available/gitlab
+If you intend to enable GitLab pages, there is a separate Nginx config you need
+to use. Read all about the needed configuration at the
+[GitLab Pages administration guide](../administration/pages/index.md).
+
**Note:** If you want to use HTTPS, replace the `gitlab` Nginx config with `gitlab-ssl`. See [Using HTTPS](#using-https) for HTTPS configuration details.
### Test Configuration
@@ -563,7 +624,7 @@ Using a self-signed certificate is discouraged but if you must use it follow the
### Enable Reply by email
-See the ["Reply by email" documentation](../incoming_email/README.md) for more information on how to set this up.
+See the ["Reply by email" documentation](../administration/reply_by_email.md) for more information on how to set this up.
### LDAP Authentication
@@ -602,6 +663,12 @@ If you want to connect the Redis server via socket, then use the "unix:" URL sch
production:
url: unix:/path/to/redis/socket
+Also you can use environment variables in the `config/resque.yml` file:
+
+ # example
+ production:
+ url: <%= ENV.fetch('GITLAB_REDIS_URL') %>
+
### Custom SSH Connection
If you are running SSH on a non-standard port, you must change the GitLab user's SSH config.
@@ -628,6 +695,12 @@ misconfigured gitlab-workhorse instance. Double-check that you've
[installed Go](#3-go), [installed gitlab-workhorse](#install-gitlab-workhorse),
and correctly [configured Nginx](#site-configuration).
+### google-protobuf "LoadError: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14' not found"
+
+This can happen on some platforms for some versions of the
+google-protobuf gem. The workaround is to [install a source-only
+version of this gem](google-protobuf.md).
+
[RVM]: https://rvm.io/ "RVM Homepage"
[rbenv]: https://github.com/sstephenson/rbenv "rbenv on GitHub"
[chruby]: https://github.com/postmodern/chruby "chruby on GitHub"
diff --git a/doc/install/kubernetes/gitlab_chart.md b/doc/install/kubernetes/gitlab_chart.md
new file mode 100644
index 00000000000..d2442a4fbde
--- /dev/null
+++ b/doc/install/kubernetes/gitlab_chart.md
@@ -0,0 +1,476 @@
+# GitLab Helm Chart
+> Officially supported cloud providers are Google Container Service and Azure Container Service.
+
+> Officially supported schedulers are Kubernetes and Terraform.
+
+The `gitlab` Helm chart deploys GitLab into your Kubernetes cluster.
+
+This chart includes the following:
+
+- Deployment using the [gitlab-ce](https://hub.docker.com/r/gitlab/gitlab-ce) or [gitlab-ee](https://hub.docker.com/r/gitlab/gitlab-ee) container image
+- ConfigMap containing the `gitlab.rb` contents that configure [Omnibus GitLab](https://docs.gitlab.com/omnibus/settings/configuration.html#configuration-options)
+- Persistent Volume Claims for Data, Config, Logs, and Registry Storage
+- A Kubernetes service
+- Optional Redis deployment using the [Redis Chart](https://github.com/kubernetes/charts/tree/master/stable/redis) (defaults to enabled)
+- Optional PostgreSQL deployment using the [PostgreSQL Chart](https://github.com/kubernetes/charts/tree/master/stable/postgresql) (defaults to enabled)
+- Optional Ingress (defaults to disabled)
+
+## Prerequisites
+
+- _At least_ 3 GB of RAM available on your cluster, in chunks of 1 GB. 41GB of storage and 2 CPU are also required.
+- Kubernetes 1.4+ with Beta APIs enabled
+- [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) provisioner support in the underlying infrastructure
+- The ability to point a DNS entry or URL at your GitLab install
+- The `kubectl` CLI installed locally and authenticated for the cluster
+- The Helm Client installed locally
+- The Helm Server (Tiller) already installed and running in the cluster, by running `helm init`
+- The GitLab Helm Repo [added to your Helm Client](index.md#add-the-gitlab-helm-repository)
+
+## Configuring GitLab
+
+Create a `values.yaml` file for your GitLab configuration. See the
+[Helm docs](https://github.com/kubernetes/helm/blob/master/docs/chart_template_guide/values_files.md)
+for information on how your values file will override the defaults.
+
+The default configuration can always be [found in the `values.yaml`](https://gitlab.com/charts/charts.gitlab.io/blob/master/charts/gitlab/values.yaml), in the chart repository.
+
+### Required configuration
+
+In order for GitLab to function, your config file **must** specify the following:
+
+- An `externalUrl` that GitLab will be reachable at.
+
+### Choosing GitLab Edition
+
+The Helm chart defaults to installing GitLab CE. This can be controlled by setting the `edition` variable in your values.
+
+Setting `edition` to GitLab Enterprise Edition (EE) in your `values.yaml`
+
+```yaml
+edition: EE
+
+externalUrl: 'http://gitlab.example.com'
+```
+
+### Choosing a different GitLab release version
+
+The version of GitLab installed is based on the `edition` setting (see [section](#choosing-gitlab-edition) above), and
+the value of the corresponding helm setting: `ceImage` or `eeImage`.
+
+```yaml
+## GitLab Edition
+## ref: https://about.gitlab.com/products/
+## - CE - Community Edition
+## - EE - Enterprise Edition - (requires license issued by GitLab Inc)
+##
+edition: CE
+
+## GitLab CE image
+## ref: https://hub.docker.com/r/gitlab/gitlab-ce/tags/
+##
+ceImage: gitlab/gitlab-ce:9.1.2-ce.0
+
+## GitLab EE image
+## ref: https://hub.docker.com/r/gitlab/gitlab-ee/tags/
+##
+eeImage: gitlab/gitlab-ee:9.1.2-ee.0
+```
+
+The different images can be found in the [gitlab-ce](https://hub.docker.com/r/gitlab/gitlab-ce/tags/) and [gitlab-ee](https://hub.docker.com/r/gitlab/gitlab-ee/tags/)
+repositories on Docker Hub
+
+> **Note:**
+There is no guarantee that other release versions of GitLab, other than what are
+used by default in the chart, will be supported by a chart install.
+
+
+### Custom Omnibus GitLab configuration
+
+In addition to the configuration options provided for GitLab in the Helm Chart, you can also pass any custom configuration
+that is valid for the [Omnibus GitLab Configuration](https://docs.gitlab.com/omnibus/settings/configuration.html).
+
+The setting to pass these values in is `omnibusConfigRuby`. It accepts any valid
+Ruby code that could used in the Omnibus `/etc/gitlab/gitlab.rb` file. In
+Kubernetes, the contents will be stored in a ConfigMap.
+
+Example setting:
+
+```yaml
+omnibusConfigRuby: |
+ unicorn['worker_processes'] = 2;
+ gitlab_rails['trusted_proxies'] = ["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16"];
+```
+
+### Persistent storage
+
+By default, persistent storage is enabled for GitLab and the charts it depends
+on (Redis and PostgreSQL).
+
+Components can have their claim size set from your `values.yaml`, and each
+component allows you to optionally configure the `storageClass` variable so you
+can take advantage of faster drives on your cloud provider.
+
+Basic configuration:
+
+```yaml
+## Enable persistence using Persistent Volume Claims
+## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
+## ref: https://docs.gitlab.com/ce/install/requirements.html#storage
+##
+persistence:
+ ## This volume persists generated configuration files, keys, and certs.
+ ##
+ gitlabEtc:
+ enabled: true
+ size: 1Gi
+ ## If defined, volume.beta.kubernetes.io/storage-class: <storageClass>
+ ## Default: volume.alpha.kubernetes.io/storage-class: default
+ ##
+ # storageClass:
+ accessMode: ReadWriteOnce
+ ## This volume is used to store git data and other project files.
+ ## ref: https://docs.gitlab.com/omnibus/settings/configuration.html#storing-git-data-in-an-alternative-directory
+ ##
+ gitlabData:
+ enabled: true
+ size: 10Gi
+ ## If defined, volume.beta.kubernetes.io/storage-class: <storageClass>
+ ## Default: volume.alpha.kubernetes.io/storage-class: default
+ ##
+ # storageClass:
+ accessMode: ReadWriteOnce
+ gitlabRegistry:
+ enabled: true
+ size: 10Gi
+ ## If defined, volume.beta.kubernetes.io/storage-class: <storageClass>
+ ## Default: volume.alpha.kubernetes.io/storage-class: default
+ ##
+ # storageClass:
+
+ postgresql:
+ persistence:
+ # storageClass:
+ size: 10Gi
+ ## Configuration values for the Redis dependency.
+ ## ref: https://github.com/kubernetes/charts/blob/master/stable/redis/README.md
+ ##
+ redis:
+ persistence:
+ # storageClass:
+ size: 10Gi
+```
+
+>**Note:**
+You can make use of faster SSD drives by adding a [StorageClass] to your cluster
+and using the `storageClass` setting in the above config to the name of
+your new storage class.
+
+### Routing
+
+By default, the GitLab chart uses a service type of `LoadBalancer` which will
+result in the GitLab service being exposed externally using your cloud provider's
+load balancer.
+
+This field is configurable in your `values.yml` by setting the top-level
+`serviceType` field. See the [Service documentation][kube-srv] for more
+information on the possible values.
+
+#### Ingress routing
+
+Optionally, you can enable the Chart's ingress for use by an ingress controller
+deployed in your cluster.
+
+To enable the ingress, edit its section in your `values.yaml`:
+
+```yaml
+ingress:
+ ## If true, gitlab Ingress will be created
+ ##
+ enabled: true
+
+ ## gitlab Ingress hostnames
+ ## Must be provided if Ingress is enabled
+ ##
+ hosts:
+ - gitlab.example.com
+
+ ## gitlab Ingress annotations
+ ##
+ annotations:
+ kubernetes.io/ingress.class: nginx
+```
+
+You must also provide the list of hosts that the ingress will use. In order for
+you ingress controller to work with the GitLab Ingress, you will need to specify
+its class in an annotation.
+
+>**Note:**
+The Ingress alone doesn't expose GitLab externally. You need to have a Ingress controller setup to do that.
+Setting up an Ingress controller can be done by installing the `nginx-ingress` helm chart. But be sure
+to read the [documentation](https://github.com/kubernetes/charts/blob/master/stable/nginx-ingress/README.md).
+>**Note:**
+If you would like to use the Registry, you will also need to ensure your Ingress supports a [sufficiently large request size](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size).
+
+#### Preserving Source IPs
+
+If you are using the `LoadBalancer` serviceType you may run into issues where user IP addresses in the GitLab
+logs, and used in abuse throttling are not accurate. This is due to how Kubernetes uses source NATing on cluster nodes without endpoints.
+
+See the [Kubernetes documentation](https://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-typeloadbalancer) for more information.
+
+To fix this you can add the following service annotation to your `values.yaml`
+
+```yaml
+## For minikube, set this to NodePort, elsewhere use LoadBalancer
+## ref: http://kubernetes.io/docs/user-guide/services/#publishing-services---service-types
+##
+serviceType: LoadBalancer
+
+## Optional annotations for gitlab service.
+serviceAnnotations:
+ service.beta.kubernetes.io/external-traffic: "OnlyLocal"
+```
+
+>**Note:**
+If you are using the ingress routing, you will likely also need to specify the annotation on the service for the ingress
+controller. For `nginx-ingress` you can check the
+[configuration documentation](https://github.com/kubernetes/charts/blob/master/stable/nginx-ingress/README.md#configuration)
+on how to add the annotation to the `controller.service.annotations` array.
+
+>**Note:**
+When using the `nginx-ingress` controller on Google Container Engine (GKE), and using the `external-traffic` annotation,
+you will need to additionally set the `controller.kind` to be DaemonSet. Otherwise only pods running on the same node
+as the nginx controller will be able to reach GitLab. This may result in pods within your cluster not being able to reach GitLab.
+See the [Kubernetes documentation](https://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-typeloadbalancer) and
+[nginx-ingress configuration documentation](https://github.com/kubernetes/charts/blob/master/stable/nginx-ingress/README.md#configuration)
+for more information.
+
+### External database
+
+You can configure the GitLab Helm chart to connect to an external PostgreSQL
+database.
+
+>**Note:**
+This is currently our recommended approach for a Production setup.
+
+To use an external database, in your `values.yaml`, disable the included
+PostgreSQL dependency, then configure access to your database:
+
+```yaml
+dbHost: "<reachable postgres hostname>"
+dbPassword: "<password for the user with access to the db>"
+dbUsername: "<user with read/write access to the database>"
+dbDatabase: "<database name on postgres to connect to for GitLab>"
+
+postgresql:
+ # Sets whether the PostgreSQL helm chart is used as a dependency
+ enabled: false
+```
+
+Be sure to check the GitLab documentation on how to
+[configure the external database](../requirements.md#postgresql-requirements)
+
+You can also configure the chart to use an external Redis server, but this is
+not required for basic production use:
+
+```yaml
+dbHost: "<reachable redis hostname>"
+dbPassword: "<password>"
+
+redis:
+ # Sets whether the Redis helm chart is used as a dependency
+ enabled: false
+```
+
+### Sending email
+
+By default, the GitLab container will not be able to send email from your cluster.
+In order to send email, you should configure SMTP settings in the
+`omnibusConfigRuby` section, as per the [GitLab Omnibus documentation](https://docs.gitlab.com/omnibus/settings/smtp.html).
+
+>**Note:**
+Some cloud providers restrict emails being sent out on SMTP, so you will have
+to use a SMTP service that is supported by your provider. See this
+[Google Cloud Platform page](https://cloud.google.com/compute/docs/tutorials/sending-mail/)
+as and example.
+
+Here is an example configuration for Mailgun SMTP support:
+
+```yaml
+omnibusConfigRuby: |
+ # This is example config of what you may already have in your omnibusConfigRuby object
+ unicorn['worker_processes'] = 2;
+ gitlab_rails['trusted_proxies'] = ["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16"];
+
+ # SMTP settings
+ gitlab_rails['smtp_enable'] = true
+ gitlab_rails['smtp_address'] = "smtp.mailgun.org"
+ gitlab_rails['smtp_port'] = 2525 # High port needed for Google Cloud
+ gitlab_rails['smtp_authentication'] = "plain"
+ gitlab_rails['smtp_enable_starttls_auto'] = false
+ gitlab_rails['smtp_user_name'] = "postmaster@mg.your-mail-domain"
+ gitlab_rails['smtp_password'] = "you-password"
+ gitlab_rails['smtp_domain'] = "mg.your-mail-domain"
+```
+
+### HTTPS configuration
+
+To setup HTTPS access to your GitLab server, first you need to configure the
+chart to use the [ingress](#ingress-routing).
+
+GitLab's config should be updated to support [proxied SSL](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl).
+
+In addition to having a Ingress Controller deployed and the basic ingress
+settings configured, you will also need to specify in the ingress settings
+which hosts to use HTTPS for.
+
+Make sure `externalUrl` now includes `https://` instead of `http://` in its
+value, and update the `omnibusConfigRuby` section:
+
+```yaml
+externalUrl: 'https://gitlab.example.com'
+
+omnibusConfigRuby: |
+ # This is example config of what you may already have in your omnibusConfigRuby object
+ unicorn['worker_processes'] = 2;
+ gitlab_rails['trusted_proxies'] = ["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16"];
+
+ # These are the settings needed to support proxied SSL
+ nginx['listen_port'] = 80
+ nginx['listen_https'] = false
+ nginx['proxy_set_headers'] = {
+ "X-Forwarded-Proto" => "https",
+ "X-Forwarded-Ssl" => "on"
+ }
+
+ingress:
+ enabled: true
+ annotations:
+ kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: 'true' Annotation used for letsencrypt support
+
+ hosts:
+ - gitlab.example.com
+
+ ## gitlab Ingress TLS configuration
+ ## Secrets must be created in the namespace, and is not done for you in this chart
+ ##
+ tls:
+ - secretName: gitlab-tls
+ hosts:
+ - gitlab.example.com
+```
+
+You will need to create the named secret in your cluster, specifying the private
+and public certificate pair using the format outlined in the
+[ingress documentation](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls).
+
+Alternatively, you can use the `kubernetes.io/tls-acme` annotation, and install
+the `kube-lego` chart to your cluster to have Let's Encrypt issue your
+certificate. See the [kube-lego documentation](https://github.com/kubernetes/charts/blob/master/stable/kube-lego/README.md)
+for more information.
+
+### Enabling the GitLab Container Registry
+
+The GitLab Registry is disabled by default but can be enabled by providing an
+external URL for it in the configuration. In order for the Registry to be easily
+used by GitLab CI and your Kubernetes cluster, you will need to set it up with
+a TLS certificate, so these examples will include the ingress settings for that
+as well. See the [HTTPS Configuration section](#https-configuration)
+for more explanation on some of these settings.
+
+Example config:
+
+```yaml
+externalUrl: 'https://gitlab.example.com'
+
+omnibusConfigRuby: |
+ # This is example config of what you may already have in your omnibusConfigRuby object
+ unicorn['worker_processes'] = 2;
+ gitlab_rails['trusted_proxies'] = ["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16"];
+
+ registry_external_url 'https://registry.example.com';
+
+ # These are the settings needed to support proxied SSL
+ nginx['listen_port'] = 80
+ nginx['listen_https'] = false
+ nginx['proxy_set_headers'] = {
+ "X-Forwarded-Proto" => "https",
+ "X-Forwarded-Ssl" => "on"
+ }
+ registry_nginx['listen_port'] = 80
+ registry_nginx['listen_https'] = false
+ registry_nginx['proxy_set_headers'] = {
+ "X-Forwarded-Proto" => "https",
+ "X-Forwarded-Ssl" => "on"
+ }
+
+ingress:
+ enabled: true
+ annotations:
+ kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: 'true' Annotation used for letsencrypt support
+
+ hosts:
+ - gitlab.example.com
+ - registry.example.com
+
+ ## gitlab Ingress TLS configuration
+ ## Secrets must be created in the namespace, and is not done for you in this chart
+ ##
+ tls:
+ - secretName: gitlab-tls
+ hosts:
+ - gitlab.example.com
+ - registry.example.com
+```
+
+## Installing GitLab using the Helm Chart
+> You may see a temporary error message `SchedulerPredicates failed due to PersistentVolumeClaim is not bound` while storage provisions. Once the storage provisions, the pods will automatically restart. This may take a couple minutes depending on your cloud provider. If the error persists, please review the [prerequisites](#prerequisites) to ensure you have enough RAM, CPU, and storage.
+
+Once you [have configured](#configuration) GitLab in your `values.yml` file,
+run the following:
+
+```bash
+helm install --namespace <NAMESPACE> --name gitlab -f <CONFIG_VALUES_FILE> gitlab/gitlab
+```
+
+where:
+
+- `<NAMESPACE>` is the Kubernetes namespace where you want to install GitLab.
+- `<CONFIG_VALUES_FILE>` is the path to values file containing your custom
+ configuration. See the [Configuration](#configuration) section to create it.
+
+## Updating GitLab using the Helm Chart
+
+Once your GitLab Chart is installed, configuration changes and chart updates
+should we done using `helm upgrade`
+
+```bash
+helm upgrade --namespace <NAMESPACE> -f <CONFIG_VALUES_FILE> <RELEASE-NAME> gitlab/gitlab
+```
+
+where:
+
+- `<NAMESPACE>` is the Kubernetes namespace where GitLab is installed.
+- `<CONFIG_VALUES_FILE>` is the path to values file containing your custom
+ [configuration] (#configuration).
+- `<RELEASE-NAME>` is the name you gave the chart when installing it.
+ In the [Install section](#installing) we called it `gitlab`.
+
+## Uninstalling GitLab using the Helm Chart
+
+To uninstall the GitLab Chart, run the following:
+
+```bash
+helm delete --namespace <NAMESPACE> <RELEASE-NAME>
+```
+
+where:
+
+- `<NAMESPACE>` is the Kubernetes namespace where GitLab is installed.
+- `<RELEASE-NAME>` is the name you gave the chart when installing it.
+ In the [Install section](#installing) we called it `gitlab`.
+
+[kube-srv]: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types
+[storageclass]: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#storageclasses
diff --git a/doc/install/kubernetes/gitlab_runner_chart.md b/doc/install/kubernetes/gitlab_runner_chart.md
new file mode 100644
index 00000000000..b8bc0795f2e
--- /dev/null
+++ b/doc/install/kubernetes/gitlab_runner_chart.md
@@ -0,0 +1,178 @@
+# GitLab Runner Helm Chart
+> Officially supported cloud providers are Google Container Service and Azure Container Service.
+
+> Officially supported schedulers are Kubernetes and Terraform.
+
+The `gitlab-runner` Helm chart deploys a GitLab Runner instance into your
+Kubernetes cluster.
+
+This chart configures the Runner to:
+
+- Run using the GitLab Runner [Kubernetes executor](https://docs.gitlab.com/runner/install/kubernetes.html)
+- For each new job it receives from [GitLab CI](https://about.gitlab.com/features/gitlab-ci-cd/), it will provision a
+ new pod within the specified namespace to run it.
+
+## Prerequisites
+
+- Your GitLab Server's API is reachable from the cluster
+- Kubernetes 1.4+ with Beta APIs enabled
+- The `kubectl` CLI installed locally and authenticated for the cluster
+- The Helm Client installed locally
+- The Helm Server (Tiller) already installed and running in the cluster, by running `helm init`
+- The GitLab Helm Repo added to your Helm Client. See [Adding GitLab Helm Repo](index.md#add-the-gitlab-helm-repository)
+
+## Configuring GitLab Runner using the Helm Chart
+
+Create a `values.yaml` file for your GitLab Runner configuration. See [Helm docs](https://github.com/kubernetes/helm/blob/master/docs/chart_template_guide/values_files.md)
+for information on how your values file will override the defaults.
+
+The default configuration can always be found in the [values.yaml](https://gitlab.com/charts/charts.gitlab.io/blob/master/charts/gitlab-runner/values.yaml) in the chart repository.
+
+### Required configuration
+
+In order for GitLab Runner to function, your config file **must** specify the following:
+
+ - `gitlabURL` - the GitLab Server URL (with protocol) to register the runner against
+ - `runnerRegistrationToken` - The Registration Token for adding new Runners to the GitLab Server. This must be
+ retrieved from your GitLab Instance. See the [GitLab Runner Documentation](../../ci/runners/README.md#creating-and-registering-a-runner) for more information.
+
+### Other configuration
+
+The rest of the configuration is [documented in the `values.yaml`](https://gitlab.com/charts/charts.gitlab.io/blob/master/charts/gitlab-runner/values.yaml) in the chart repository.
+
+Here is a snippet of the important settings:
+
+```yaml
+## The GitLab Server URL (with protocol) that want to register the runner against
+## ref: https://docs.gitlab.com/runner/commands/README.html#gitlab-runner-register
+##
+gitlabURL: http://gitlab.your-domain.com/
+
+## The Registration Token for adding new Runners to the GitLab Server. This must
+## be retreived from your GitLab Instance.
+## ref: https://docs.gitlab.com/ce/ci/runners/README.html#creating-and-registering-a-runner
+##
+runnerRegistrationToken: ""
+
+## Configure the maximum number of concurrent jobs
+## ref: https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section
+##
+concurrent: 10
+
+## Defines in seconds how often to check GitLab for a new builds
+## ref: https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section
+##
+checkInterval: 30
+
+## Configuration for the Pods that that the runner launches for each new job
+##
+runners:
+ ## Default container image to use for builds when none is specified
+ ##
+ image: ubuntu:16.04
+
+ ## Run all containers with the privileged flag enabled
+ ## This will allow the docker:dind image to run if you need to run Docker
+ ## commands. Please read the docs before turning this on:
+ ## ref: https://docs.gitlab.com/runner/executors/kubernetes.html#using-docker-dind
+ ##
+ privileged: false
+
+ ## Namespace to run Kubernetes jobs in (defaults to 'default')
+ ##
+ # namespace:
+
+ ## Build Container specific configuration
+ ##
+ builds:
+ # cpuLimit: 200m
+ # memoryLimit: 256Mi
+ cpuRequests: 100m
+ memoryRequests: 128Mi
+
+ ## Service Container specific configuration
+ ##
+ services:
+ # cpuLimit: 200m
+ # memoryLimit: 256Mi
+ cpuRequests: 100m
+ memoryRequests: 128Mi
+
+ ## Helper Container specific configuration
+ ##
+ helpers:
+ # cpuLimit: 200m
+ # memoryLimit: 256Mi
+ cpuRequests: 100m
+ memoryRequests: 128Mi
+
+```
+
+### Running Docker-in-Docker containers with GitLab Runners
+
+See [Running Privileged Containers for the Runners](#running-privileged-containers-for-the-runners) for how to enable it,
+and the [GitLab CI Runner documentation](https://docs.gitlab.com/runner/executors/kubernetes.html#using-docker-in-your-builds) on running dind.
+
+### Running privileged containers for the Runners
+
+You can tell the GitLab Runner to run using privileged containers. You may need
+this enabled if you need to use the Docker executable within your GitLab CI jobs.
+
+This comes with several risks that you can read about in the
+[GitLab CI Runner documentation](https://docs.gitlab.com/runner/executors/kubernetes.html#using-docker-in-your-builds).
+
+If you are okay with the risks, and your GitLab CI Runner instance is registered
+against a specific project in GitLab that you trust the CI jobs of, you can
+enable privileged mode in `values.yaml`:
+
+```yaml
+runners:
+ ## Run all containers with the privileged flag enabled
+ ## This will allow the docker:dind image to run if you need to run Docker
+ ## commands. Please read the docs before turning this on:
+ ## ref: https://docs.gitlab.com/runner/executors/kubernetes.html#using-docker-dind
+ ##
+ privileged: true
+```
+
+## Installing GitLab Runner using the Helm Chart
+
+Once you [have configured](#configuration) GitLab Runner in your `values.yml` file,
+run the following:
+
+```bash
+helm install --namespace <NAMESPACE> --name gitlab-runner -f <CONFIG_VALUES_FILE> gitlab/gitlab-runner
+```
+
+- `<NAMESPACE>` is the Kubernetes namespace where you want to install the GitLab Runner.
+- `<CONFIG_VALUES_FILE>` is the path to values file containing your custom configuration. See the
+ [Configuration](#configuration) section to create it.
+
+## Updating GitLab Runner using the Helm Chart
+
+Once your GitLab Runner Chart is installed, configuration changes and chart updates should we done using `helm upgrade`
+
+```bash
+helm upgrade --namespace <NAMESPACE> -f <CONFIG_VALUES_FILE> <RELEASE-NAME> gitlab/gitlab-runner
+```
+
+Where:
+- `<NAMESPACE>` is the Kubernetes namespace where GitLab Runner is installed
+- `<CONFIG_VALUES_FILE>` is the path to values file containing your custom configuration. See the
+ [Configuration](#configuration) section to create it.
+- `<RELEASE-NAME>` is the name you gave the chart when installing it.
+ In the [Install section](#installing) we called it `gitlab-runner`.
+
+## Uninstalling GitLab Runner using the Helm Chart
+
+To uninstall the GitLab Runner Chart, run the following:
+
+```bash
+helm delete --namespace <NAMESPACE> <RELEASE-NAME>
+```
+
+where:
+
+- `<NAMESPACE>` is the Kubernetes namespace where GitLab Runner is installed
+- `<RELEASE-NAME>` is the name you gave the chart when installing it.
+ In the [Install section](#installing) we called it `gitlab-runner`.
diff --git a/doc/install/kubernetes/index.md b/doc/install/kubernetes/index.md
new file mode 100644
index 00000000000..5ea08869a9b
--- /dev/null
+++ b/doc/install/kubernetes/index.md
@@ -0,0 +1,47 @@
+# Installing GitLab on Kubernetes
+> Officially supported cloud providers are Google Container Service and Azure Container Service.
+
+> Officially supported schedulers are Kubernetes, Terraform and Tectonic.
+
+The easiest method to deploy GitLab in [Kubernetes](https://kubernetes.io/) is
+to take advantage of the official GitLab Helm charts. [Helm] is a package
+management tool for Kubernetes, allowing apps to be easily managed via their
+Charts. A [Chart] is a detailed description of the application including how it
+should be deployed, upgraded, and configured.
+
+The GitLab Helm repository is located at https://charts.gitlab.io.
+You can report any issues related to GitLab's Helm Charts at
+https://gitlab.com/charts/charts.gitlab.io/issues.
+Contributions and improvements are also very welcome.
+
+## Prerequisites
+
+To use the charts, the Helm tool must be installed and initialized. The best
+place to start is by reviewing the [Helm Quick Start Guide][helm-quick].
+
+## Add the GitLab Helm repository
+
+Once Helm has been installed, the GitLab chart repository must be added:
+
+```bash
+helm repo add gitlab https://charts.gitlab.io
+```
+
+After adding the repository, Helm must be re-initialized:
+
+```bash
+helm init
+```
+
+## Using the GitLab Helm Charts
+
+GitLab makes available two Helm Charts, one for the GitLab server and another
+for the Runner. More detailed information on installing and configuring each
+Chart can be found below:
+
+- [Install GitLab](gitlab_chart.md)
+- [Install GitLab Runner](gitlab_runner_chart.md)
+
+[chart]: https://github.com/kubernetes/charts
+[helm-quick]: https://github.com/kubernetes/helm/blob/master/docs/quickstart.md
+[helm]: https://github.com/kubernetes/helm/blob/master/README.md
diff --git a/doc/install/relative_url.md b/doc/install/relative_url.md
index 44d2a14f366..713d11b75e4 100644
--- a/doc/install/relative_url.md
+++ b/doc/install/relative_url.md
@@ -113,14 +113,6 @@ Make sure to follow all steps below:
If you are using a custom init script, make sure to edit the above
gitlab-workhorse setting as needed.
-1. After all the above changes recompile the assets. This is an important task
- and will take some time to complete depending on the server resources:
-
- ```
- cd /home/git/gitlab
- sudo -u git -H bundle exec rake assets:clean assets:precompile RAILS_ENV=production
- ```
-
1. [Restart GitLab][] for the changes to take effect.
### Disable relative URL in GitLab
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 766a7119943..a3d676433e6 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -15,11 +15,11 @@ For the installations options please see [the installation page on the GitLab we
### Unsupported Unix distributions
-- OS X
- Arch Linux
- Fedora
-- Gentoo
- FreeBSD
+- Gentoo
+- macOS
On the above unsupported distributions is still possible to install GitLab yourself.
Please see the [installation from source guide](installation.md) and the [installation guides](https://about.gitlab.com/installation/) for more information.
@@ -86,53 +86,62 @@ if your available memory changes.
Notice: The 25 workers of Sidekiq will show up as separate processes in your process overview (such as top or htop) but they share the same RAM allocation since Sidekiq is a multithreaded application. Please see the section below about Unicorn workers for information about many you need of those.
-## GitLab Runner
-
-We strongly advise against installing GitLab Runner on the same machine you plan
-to install GitLab on. Depending on how you decide to configure GitLab Runner and
-what tools you use to exercise your application in the CI environment, GitLab
-Runner can consume significant amount of available memory.
-
-Memory consumption calculations, that are available above, will not be valid if
-you decide to run GitLab Runner and the GitLab Rails application on the same
-machine.
-
-It is also not safe to install everything on a single machine, because of the
-[security reasons] - especially when you plan to use shell executor with GitLab
-Runner.
-
-We recommend using a separate machine for each GitLab Runner, if you plan to
-use the CI features.
-
-[security reasons]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/security/index.md
+## Database
-## Unicorn Workers
+The server running the database should have _at least_ 5-10 GB of storage
+available, though the exact requirements depend on the size of the GitLab
+installation (e.g. the number of users, projects, etc).
-It's possible to increase the amount of unicorn workers and this will usually help for to reduce the response time of the applications and increase the ability to handle parallel requests.
+We currently support the following databases:
-For most instances we recommend using: CPU cores + 1 = unicorn workers.
-So for a machine with 2 cores, 3 unicorn workers is ideal.
+- PostgreSQL (highly recommended)
+- MySQL/MariaDB (strongly discouraged, not all GitLab features are supported, no support for [MySQL/MariaDB GTID](https://mariadb.com/kb/en/mariadb/gtid/))
-For all machines that have 2GB and up we recommend a minimum of three unicorn workers.
-If you have a 1GB machine we recommend to configure only two Unicorn workers to prevent excessive swapping.
+We highly recommend the use of PostgreSQL instead of MySQL/MariaDB as not all
+features of GitLab work with MySQL/MariaDB:
-To change the Unicorn workers when you have the Omnibus package please see [the Unicorn settings in the Omnibus GitLab documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/unicorn.md#unicorn-settings).
+1. MySQL support for subgroups was [dropped with GitLab 9.3][post].
+ See [issue #30472][30472] for more information.
+1. GitLab Geo does [not support MySQL](https://docs.gitlab.com/ee/gitlab-geo/database.html#mysql-replication).
+1. [Zero downtime migrations][zero] do not work with MySQL
+1. We expect this list to grow over time.
-## Database
+Existing users using GitLab with MySQL/MariaDB are advised to
+[migrate to PostgreSQL](../update/mysql_to_postgresql.md) instead.
-If you want to run the database separately expect a size of about 1 MB per user.
+[30472]: https://gitlab.com/gitlab-org/gitlab-ce/issues/30472
+[zero]: ../update/README.md#upgrading-without-downtime
+[post]: https://about.gitlab.com/2017/06/22/gitlab-9-3-released/#dropping-support-for-subgroups-in-mysql
### PostgreSQL Requirements
+As of GitLab 9.3, PostgreSQL 9.2 or newer is required, and earlier versions are
+not supported. We highly recommend users to use at least PostgreSQL 9.6 as this
+is the PostgreSQL version used for development and testing.
+
Users using PostgreSQL must ensure the `pg_trgm` extension is loaded into every
GitLab database. This extension can be enabled (using a PostgreSQL super user)
by running the following query for every database:
- CREATE EXTENSION pg_trgm;
+```
+CREATE EXTENSION pg_trgm;
+```
On some systems you may need to install an additional package (e.g.
`postgresql-contrib`) for this extension to become available.
+## Unicorn Workers
+
+It's possible to increase the amount of unicorn workers and this will usually help to reduce the response time of the applications and increase the ability to handle parallel requests.
+
+For most instances we recommend using: CPU cores + 1 = unicorn workers.
+So for a machine with 2 cores, 3 unicorn workers is ideal.
+
+For all machines that have 2GB and up we recommend a minimum of three unicorn workers.
+If you have a 1GB machine we recommend to configure only two Unicorn workers to prevent excessive swapping.
+
+To change the Unicorn workers when you have the Omnibus package please see [the Unicorn settings in the Omnibus GitLab documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/unicorn.md#unicorn-settings).
+
## Redis and Sidekiq
Redis stores all user sessions and the background task queue.
@@ -141,11 +150,38 @@ Sidekiq processes the background jobs with a multithreaded process.
This process starts with the entire Rails stack (200MB+) but it can grow over time due to memory leaks.
On a very active server (10,000 active users) the Sidekiq process can use 1GB+ of memory.
+## Prometheus and its exporters
+
+As of Omnibus GitLab 9.0, [Prometheus](https://prometheus.io) and its related
+exporters are enabled by default, to enable easy and in depth monitoring of
+GitLab. Approximately 200MB of memory will be consumed by these processes, with
+default settings.
+
+If you would like to disable Prometheus and it's exporters or read more information
+about it, check the [Prometheus documentation](../administration/monitoring/prometheus/index.md).
+
+## GitLab Runner
+
+We strongly advise against installing GitLab Runner on the same machine you plan
+to install GitLab on. Depending on how you decide to configure GitLab Runner and
+what tools you use to exercise your application in the CI environment, GitLab
+Runner can consume significant amount of available memory.
+
+Memory consumption calculations, that are available above, will not be valid if
+you decide to run GitLab Runner and the GitLab Rails application on the same
+machine.
+
+It is also not safe to install everything on a single machine, because of the
+[security reasons] - especially when you plan to use shell executor with GitLab
+Runner.
+
+We recommend using a separate machine for each GitLab Runner, if you plan to
+use the CI features.
+
+[security reasons]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/security/index.md
+
## Supported web browsers
-- Chrome (Latest stable version)
-- Firefox (Latest released version and [latest ESR version](https://www.mozilla.org/en-US/firefox/organizations/))
-- Safari 7+ (known problem: required fields in html5 do not work)
-- Opera (Latest released version)
-- Internet Explorer (IE) 11+ but please make sure that you have the `Compatibility View` mode disabled.
-- Edge (Latest stable version)
+We support the current and the previous major release of Firefox, Chrome/Chromium, Safari and Microsoft browsers (Microsoft Edge and Internet Explorer 11).
+
+Each time a new browser version is released, we begin supporting that version and stop supporting the third most recent version.
diff --git a/doc/integration/README.md b/doc/integration/README.md
index c2fd299db07..e56e58498a6 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -5,29 +5,28 @@ trackers and external authentication.
See the documentation below for details on how to configure these services.
-- [Jira](../project_services/jira.md) Integrate with the JIRA issue tracker
+- [JIRA](../user/project/integrations/jira.md) Integrate with the JIRA issue tracker
- [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc.
- [LDAP](ldap.md) Set up sign in via LDAP
-- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab.com, Google, Bitbucket, Facebook, Shibboleth, SAML, Crowd and Azure
+- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab.com, Google, Bitbucket, Facebook, Shibboleth, SAML, Crowd, Azure and Authentiq ID
- [SAML](saml.md) Configure GitLab as a SAML 2.0 Service Provider
- [CAS](cas.md) Configure GitLab to sign in using CAS
- [OAuth2 provider](oauth_provider.md) OAuth2 application creation
+- [OpenID Connect](openid_connect_provider.md) Use GitLab as an identity provider
- [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages
- [reCAPTCHA](recaptcha.md) Configure GitLab to use Google reCAPTCHA for new users
- [Akismet](akismet.md) Configure Akismet to stop spam
- [Koding](../administration/integration/koding.md) Configure Koding to use IDE integration
+- [PlantUML](../administration/integration/plantuml.md) Configure PlantUML to use diagrams in AsciiDoc documents.
-GitLab Enterprise Edition contains [advanced Jenkins support][jenkins].
-
-[jenkins]: http://docs.gitlab.com/ee/integration/jenkins.html
-
+> GitLab Enterprise Edition contains [advanced Jenkins support][jenkins].
## Project services
Integration with services such as Campfire, Flowdock, Gemnasium, HipChat,
Pivotal Tracker, and Slack are available in the form of a [Project Service][].
-[Project Service]: ../project_services/project_services.md
+[Project Service]: ../user/project/integrations/project_services.md
## SSL certificate errors
@@ -44,11 +43,15 @@ This [resource](http://kb.kerio.com/product/kerio-connect/server-configuration/s
has all the information you need to add a certificate to the main trusted chain.
This [answer](http://superuser.com/questions/437330/how-do-you-add-a-certificate-authority-ca-to-ubuntu)
-at SuperUser also has relevant information.
+at Super User also has relevant information.
**Omnibus Trusted Chain**
-It is enough to concatenate the certificate to the main trusted certificate:
+[Install the self signed certificate or custom certificate authorities](http://docs.gitlab.com/omnibus/common_installation_problems/README.html#using-self-signed-certificate-or-custom-certificate-authorities)
+in to GitLab Omnibus.
+
+It is enough to concatenate the certificate to the main trusted certificate
+however it may be overwritten during upgrades:
```bash
cat jira.pem >> /opt/gitlab/embedded/ssl/certs/cacert.pem
@@ -59,3 +62,5 @@ After that restart GitLab with:
```bash
sudo gitlab-ctl restart
```
+
+[jenkins]: http://docs.gitlab.com/ee/integration/jenkins.html
diff --git a/doc/integration/auth0.md b/doc/integration/auth0.md
index e5247082a89..c39d7ab57c6 100644
--- a/doc/integration/auth0.md
+++ b/doc/integration/auth0.md
@@ -54,7 +54,7 @@ for initial settings.
gitlab_rails['omniauth_providers'] = [
{
"name" => "auth0",
- "args" => { client_id: 'YOUR_AUTH0_CLIENT_ID'',
+ "args" => { client_id: 'YOUR_AUTH0_CLIENT_ID',
client_secret: 'YOUR_AUTH0_CLIENT_SECRET',
namespace: 'YOUR_AUTH0_DOMAIN'
}
@@ -80,10 +80,13 @@ from step 5.
1. Change `YOUR_AUTH0_CLIENT_SECRET` to the client secret from the Auth0 Console
page from step 5.
-1. Save the file and [reconfigure GitLab](../administration/restart_gitlab.md)
-for the changes to take effect.
+1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you
+ installed GitLab via Omnibus or from source respectively.
On the sign in page there should now be an Auth0 icon below the regular sign in
form. Click the icon to begin the authentication process. Auth0 will ask the
user to sign in and authorize the GitLab application. If everything goes well
the user will be returned to GitLab and will be signed in.
+
+[reconfigure]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
diff --git a/doc/integration/azure.md b/doc/integration/azure.md
index 48dddf7df44..5e3e9f5ab77 100644
--- a/doc/integration/azure.md
+++ b/doc/integration/azure.md
@@ -78,6 +78,10 @@ To enable the Microsoft Azure OAuth2 OmniAuth provider you must register your ap
1. Save the configuration file.
-1. Restart GitLab for the changes to take effect.
+1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you
+ installed GitLab via Omnibus or from source respectively.
On the sign in page there should now be a Microsoft icon below the regular sign in form. Click the icon to begin the authentication process. Microsoft will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in.
+
+[reconfigure]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md
index 556d71b8b76..2a14c0397ca 100644
--- a/doc/integration/bitbucket.md
+++ b/doc/integration/bitbucket.md
@@ -5,7 +5,7 @@ Bitbucket.org account.
## Overview
-You can set up Bitbucket.org as an OAuth provider so that you can use your
+You can set up Bitbucket.org as an OAuth2 provider so that you can use your
credentials to authenticate into GitLab or import your projects from
Bitbucket.org.
@@ -18,8 +18,10 @@ Bitbucket.org.
## Bitbucket OmniAuth provider
> **Note:**
-Make sure to first follow the [Initial OmniAuth configuration][init-oauth]
-before proceeding with setting up the Bitbucket integration.
+GitLab 8.15 significantly simplified the way to integrate Bitbucket.org with
+GitLab. You are encouraged to upgrade your GitLab instance if you haven't done
+already. If you're using GitLab 8.14 and below, [use the previous integration
+docs][bb-old].
To enable the Bitbucket OmniAuth provider you must register your application
with Bitbucket.org. Bitbucket will generate an application ID and secret key for
@@ -38,20 +40,23 @@ you to use.
| :--- | :---------- |
| **Name** | This can be anything. Consider something like `<Organization>'s GitLab` or `<Your Name>'s GitLab` or something else descriptive. |
| **Application description** | Fill this in if you wish. |
- | **Callback URL** | Leave blank. |
+ | **Callback URL** | The URL to your GitLab installation, e.g., `https://gitlab.example.com`. |
| **URL** | The URL to your GitLab installation, e.g., `https://gitlab.example.com`. |
+ NOTE: Starting in GitLab 8.15, you MUST specify a callback URL, or you will
+ see an "Invalid redirect_uri" message. For more details, see [the
+ Bitbucket documentation](https://confluence.atlassian.com/bitbucket/oauth-faq-338365710.html).
+
And grant at least the following permissions:
```
- Account: Email
- Repositories: Read, Admin
+ Account: Email, Read
+ Repositories: Read
+ Pull Requests: Read
+ Issues: Read
+ Wiki: Read and Write
```
- >**Note:**
- It may seem a little odd to giving GitLab admin permissions to repositories,
- but this is needed in order for GitLab to be able to clone the repositories.
-
![Bitbucket OAuth settings page](img/bitbucket_oauth_settings_page.png)
1. Select **Save**.
@@ -93,7 +98,8 @@ you to use.
```yaml
- { name: 'bitbucket',
app_id: 'BITBUCKET_APP_KEY',
- app_secret: 'BITBUCKET_APP_SECRET' }
+ app_secret: 'BITBUCKET_APP_SECRET',
+ url: 'https://bitbucket.org/' }
```
---
@@ -112,100 +118,12 @@ well, the user will be returned to GitLab and will be signed in.
## Bitbucket project import
-To allow projects to be imported directly into GitLab, Bitbucket requires two
-extra setup steps compared to [GitHub](github.md) and [GitLab.com](gitlab.md).
-
-Bitbucket doesn't allow OAuth applications to clone repositories over HTTPS, and
-instead requires GitLab to use SSH and identify itself using your GitLab
-server's SSH key.
-
-To be able to access repositories on Bitbucket, GitLab will automatically
-register your public key with Bitbucket as a deploy key for the repositories to
-be imported. Your public key needs to be at `~/.ssh/bitbucket_rsa` which
-translates to `/var/opt/gitlab/.ssh/bitbucket_rsa` for Omnibus packages and to
-`/home/git/.ssh/bitbucket_rsa.pub` for installations from source.
-
----
-
-Below are the steps that will allow GitLab to be able to import your projects
-from Bitbucket.
-
-1. Make sure you [have enabled the Bitbucket OAuth support](#bitbucket-omniauth-provider).
-1. Create a new SSH key with an **empty passphrase**:
-
- ```sh
- sudo -u git -H ssh-keygen
- ```
-
- When asked to 'Enter file in which to save the key' enter:
- `/var/opt/gitlab/.ssh/bitbucket_rsa` for Omnibus packages or
- `/home/git/.ssh/bitbucket_rsa` for installations from source. The name is
- important so make sure to get it right.
-
- > **Warning:**
- This key must NOT be associated with ANY existing Bitbucket accounts. If it
- is, the import will fail with an `Access denied! Please verify you can add
- deploy keys to this repository.` error.
-
-1. Next, you need to to configure the SSH client to use your new key. Open the
- SSH configuration file of the `git` user:
-
- ```
- # For Omnibus packages
- sudo editor /var/opt/gitlab/.ssh/config
-
- # For installations from source
- sudo editor /home/git/.ssh/config
- ```
-
-1. Add a host configuration for `bitbucket.org`:
-
- ```sh
- Host bitbucket.org
- IdentityFile ~/.ssh/bitbucket_rsa
- User git
- ```
-
-1. Save the file and exit.
-1. Manually connect to `bitbucket.org` over SSH, while logged in as the `git`
- user that GitLab will use:
-
- ```sh
- sudo -u git -H ssh bitbucket.org
- ```
-
- That step is performed because GitLab needs to connect to Bitbucket over SSH,
- in order to add `bitbucket.org` to your GitLab server's known SSH hosts.
-
-1. Verify the RSA key fingerprint you'll see in the response matches the one
- in the [Bitbucket documentation][bitbucket-docs] (the specific IP address
- doesn't matter):
-
- ```sh
- The authenticity of host 'bitbucket.org (104.192.143.1)' can't be established.
- RSA key fingerprint is SHA256:zzXQOXSRBEiUtuE8AikJYKwbHaxvSc0ojez9YXaGp1A.
- Are you sure you want to continue connecting (yes/no)?
- ```
-
-1. If the fingerprint matches, type `yes` to continue connecting and have
- `bitbucket.org` be added to your known SSH hosts. After confirming you should
- see a permission denied message. If you see an authentication successful
- message you have done something wrong. The key you are using has already been
- added to a Bitbucket account and will cause the import script to fail. Ensure
- the key you are using CANNOT authenticate with Bitbucket.
-1. Restart GitLab to allow it to find the new public key.
-
-Your GitLab server is now able to connect to Bitbucket over SSH. You should be
-able to see the "Import projects from Bitbucket" option on the New Project page
-enabled.
-
-## Acknowledgemts
-
-Special thanks to the writer behind the following article:
-
-- http://stratus3d.com/blog/2015/09/06/migrating-from-bitbucket-to-local-gitlab-server/
+Once the above configuration is set up, you can use Bitbucket to sign into
+GitLab and [start importing your projects][bb-import].
[init-oauth]: omniauth.md#initial-omniauth-configuration
+[bb-import]: ../workflow/importing/import_projects_from_bitbucket.md
+[bb-old]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-14-stable/doc/integration/bitbucket.md
[bitbucket-docs]: https://confluence.atlassian.com/bitbucket/use-the-ssh-protocol-with-bitbucket-cloud-221449711.html#UsetheSSHprotocolwithBitbucketCloud-KnownhostorBitbucket%27spublickeyfingerprints
[reconfigure]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
diff --git a/doc/integration/cas.md b/doc/integration/cas.md
index e34e306f9ac..f757edf0bc2 100644
--- a/doc/integration/cas.md
+++ b/doc/integration/cas.md
@@ -58,8 +58,11 @@ To enable the CAS OmniAuth provider you must register your application with your
1. Save the configuration file.
-1. Run `gitlab-ctl reconfigure` for the omnibus package.
-
-1. Restart GitLab for the changes to take effect.
+1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you
+ installed GitLab via Omnibus or from source respectively.
On the sign in page there should now be a CAS tab in the sign in form.
+
+[reconfigure]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
+
diff --git a/doc/integration/chat_commands.md b/doc/integration/chat_commands.md
new file mode 100644
index 00000000000..2856992ee25
--- /dev/null
+++ b/doc/integration/chat_commands.md
@@ -0,0 +1 @@
+This document was moved to [integration/slash_commands.md](slash_commands.md).
diff --git a/doc/integration/crowd.md b/doc/integration/crowd.md
index 40d93aef2a9..2bc526dc3db 100644
--- a/doc/integration/crowd.md
+++ b/doc/integration/crowd.md
@@ -1,58 +1 @@
-# Crowd OmniAuth Provider
-
-To enable the Crowd OmniAuth provider you must register your application with Crowd. To configure Crowd integration you need an application name and password.
-
-1. On your GitLab server, open the configuration file.
-
- For omnibus package:
-
- ```sh
- sudo editor /etc/gitlab/gitlab.rb
- ```
-
- For installations from source:
-
- ```sh
- cd /home/git/gitlab
-
- sudo -u git -H editor config/gitlab.yml
- ```
-
-1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
-
-1. Add the provider configuration:
-
- For omnibus package:
-
- ```ruby
- gitlab_rails['omniauth_providers'] = [
- {
- "name" => "crowd",
- "args" => {
- "crowd_server_url" => "CROWD",
- "application_name" => "YOUR_APP_NAME",
- "application_password" => "YOUR_APP_PASSWORD"
- }
- }
- ]
- ```
-
- For installations from source:
-
- ```
- - { name: 'crowd',
- args: {
- crowd_server_url: 'CROWD SERVER URL',
- application_name: 'YOUR_APP_NAME',
- application_password: 'YOUR_APP_PASSWORD' } }
- ```
-
-1. Change 'YOUR_APP_NAME' to the application name from Crowd applications page.
-
-1. Change 'YOUR_APP_PASSWORD' to the application password you've set.
-
-1. Save the configuration file.
-
-1. Restart GitLab for the changes to take effect.
-
-On the sign in page there should now be a Crowd tab in the sign in form. \ No newline at end of file
+This document was moved to [`administration/auth/crowd`](../administration/auth/crowd.md).
diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md
index 8d2c6351fb8..265c891cf83 100644
--- a/doc/integration/external-issue-tracker.md
+++ b/doc/integration/external-issue-tracker.md
@@ -18,9 +18,9 @@ The configuration is done via a project's **Services**.
To enable an external issue tracker you must configure the appropriate **Service**.
Visit the links below for details:
-- [Redmine](../project_services/redmine.md)
-- [Jira](../project_services/jira.md)
-- [Bugzilla](../project_services/bugzilla.md)
+- [Redmine](../user/project/integrations/redmine.md)
+- [Jira](../user/project/integrations/jira.md)
+- [Bugzilla](../user/project/integrations/bugzilla.md)
### Service Template
@@ -28,4 +28,4 @@ To save you the hassle from configuring each project's service individually,
GitLab provides the ability to set Service Templates which can then be
overridden in each project's settings.
-Read more on [Services Templates](../project_services/services_templates.md).
+Read more on [Services Templates](../user/project/integrations/services_templates.md).
diff --git a/doc/integration/facebook.md b/doc/integration/facebook.md
index 77bb75cbfca..a67de23b17b 100644
--- a/doc/integration/facebook.md
+++ b/doc/integration/facebook.md
@@ -92,6 +92,10 @@ something else descriptive.
1. Save the configuration file.
-1. Restart GitLab for the changes to take effect.
+1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you
+ installed GitLab via Omnibus or from source respectively.
On the sign in page there should now be a Facebook icon below the regular sign in form. Click the icon to begin the authentication process. Facebook will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in.
+
+[reconfigure]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
diff --git a/doc/integration/github.md b/doc/integration/github.md
index 8a01afd1177..b0d67db8b59 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -2,7 +2,7 @@
Import projects from GitHub and login to your GitLab instance with your GitHub account.
-To enable the GitHub OmniAuth provider you must register your application with GitHub.
+To enable the GitHub OmniAuth provider you must register your application with GitHub.
GitHub will generate an application ID and secret key for you to use.
1. Sign in to GitHub.
@@ -19,10 +19,10 @@ GitHub will generate an application ID and secret key for you to use.
- Application name: This can be anything. Consider something like `<Organization>'s GitLab` or `<Your Name>'s GitLab` or something else descriptive.
- Homepage URL: The URL to your GitLab installation. 'https://gitlab.company.com'
- Application description: Fill this in if you wish.
- - Authorization callback URL is 'http(s)://${YOUR_DOMAIN}'
+ - Authorization callback URL is 'http(s)://${YOUR_DOMAIN}'. Please make sure the port is included if your Gitlab instance is not configured on default port.
1. Select "Register application".
-1. You should now see a Client ID and Client Secret near the top right of the page (see screenshot).
+1. You should now see a Client ID and Client Secret near the top right of the page (see screenshot).
Keep this page open as you continue configuration.
![GitHub app](img/github_app.png)
@@ -48,6 +48,21 @@ GitHub will generate an application ID and secret key for you to use.
For omnibus package:
+ For GitHub.com:
+
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ "name" => "github",
+ "app_id" => "YOUR_APP_ID",
+ "app_secret" => "YOUR_APP_SECRET",
+ "args" => { "scope" => "user:email" }
+ }
+ ]
+ ```
+
+ For GitHub Enterprise:
+
```ruby
gitlab_rails['omniauth_providers'] = [
{
@@ -88,8 +103,59 @@ GitHub will generate an application ID and secret key for you to use.
1. Save the configuration file.
-1. Restart GitLab for the changes to take effect.
+1. [Reconfigure GitLab][] or [restart GitLab][] for the changes to take effect if you
+ installed GitLab via Omnibus or from source respectively.
-On the sign in page there should now be a GitHub icon below the regular sign in form.
-Click the icon to begin the authentication process. GitHub will ask the user to sign in and authorize the GitLab application.
+On the sign in page there should now be a GitHub icon below the regular sign in form.
+Click the icon to begin the authentication process. GitHub will ask the user to sign in and authorize the GitLab application.
If everything goes well the user will be returned to GitLab and will be signed in.
+
+### GitHub Enterprise with Self-Signed Certificate
+
+If you are attempting to import projects from GitHub Enterprise with a self-signed
+certificate and the imports are failing, you will need to disable SSL verification.
+It should be disabled by adding `verify_ssl` to `false` in the provider configuration
+and changing the global Git `sslVerify` option to `false` in the GitLab server.
+
+For omnibus package:
+
+```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ "name" => "github",
+ "app_id" => "YOUR_APP_ID",
+ "app_secret" => "YOUR_APP_SECRET",
+ "url" => "https://github.com/",
+ "verify_ssl" => false,
+ "args" => { "scope" => "user:email" }
+ }
+ ]
+```
+
+You will also need to disable Git SSL verification on the server hosting GitLab.
+
+```ruby
+omnibus_gitconfig['system'] = { "http" => ["sslVerify = false"] }
+```
+
+For installation from source:
+
+```
+ - { name: 'github', app_id: 'YOUR_APP_ID',
+ app_secret: 'YOUR_APP_SECRET',
+ url: "https://github.example.com/",
+ verify_ssl: false,
+ args: { scope: 'user:email' } }
+```
+
+You will also need to disable Git SSL verification on the server hosting GitLab.
+
+```
+$ git config --global http.sslVerify false
+```
+
+For the changes to take effect, [reconfigure Gitlab] if you installed
+via Omnibus, or [restart GitLab] if you installed from source.
+
+[reconfigure GitLab]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md
index 6d8f3912ede..eec40a9b8f1 100644
--- a/doc/integration/gitlab.md
+++ b/doc/integration/gitlab.md
@@ -2,7 +2,7 @@
Import projects from GitLab.com and login to your GitLab instance with your GitLab.com account.
-To enable the GitLab.com OmniAuth provider you must register your application with GitLab.com.
+To enable the GitLab.com OmniAuth provider you must register your application with GitLab.com.
GitLab.com will generate an application ID and secret key for you to use.
1. Sign in to GitLab.com
@@ -26,8 +26,8 @@ GitLab.com will generate an application ID and secret key for you to use.
1. Select "Submit".
-1. You should now see a Client ID and Client Secret near the top right of the page (see screenshot).
- Keep this page open as you continue configuration.
+1. You should now see a Client ID and Client Secret near the top right of the page (see screenshot).
+ Keep this page open as you continue configuration.
![GitLab app](img/gitlab_app.png)
1. On your GitLab server, open the configuration file.
@@ -77,8 +77,12 @@ GitLab.com will generate an application ID and secret key for you to use.
1. Save the configuration file.
-1. Restart GitLab for the changes to take effect.
+1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you
+ installed GitLab via Omnibus or from source respectively.
-On the sign in page there should now be a GitLab.com icon below the regular sign in form.
-Click the icon to begin the authentication process. GitLab.com will ask the user to sign in and authorize the GitLab application.
+On the sign in page there should now be a GitLab.com icon below the regular sign in form.
+Click the icon to begin the authentication process. GitLab.com will ask the user to sign in and authorize the GitLab application.
If everything goes well the user will be returned to your GitLab instance and will be signed in.
+
+[reconfigure]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
diff --git a/doc/integration/google.md b/doc/integration/google.md
index 82978b68a34..d5b523e6dc0 100644
--- a/doc/integration/google.md
+++ b/doc/integration/google.md
@@ -72,9 +72,25 @@ To enable the Google OAuth2 OmniAuth provider you must register your application
1. Change 'YOUR_APP_SECRET' to the client secret from the Google Developer page from step 10.
+1. Make sure that you configure GitLab to use an FQDN as Google will not accept raw IP addresses.
+
+ For Omnibus packages:
+
+ ```ruby
+ external_url 'https://gitlab.example.com'
+ ```
+
+ For installations from source:
+
+ ```yaml
+ gitlab:
+ host: https://gitlab.example.com
+ ```
+
1. Save the configuration file.
-1. Restart GitLab for the changes to take effect.
+1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you
+ installed GitLab via Omnibus or from source respectively.
On the sign in page there should now be a Google icon below the regular sign in form. Click the icon to begin the authentication process. Google will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in.
@@ -87,3 +103,6 @@ At this point, when users first try to authenticate to your GitLab installation
1. Select 'Consent screen' in the left menu. (See steps 1, 4 and 5 above for instructions on how to get here if you closed your window).
1. Scroll down until you find "Product Name". Change the product name to something more descriptive.
1. Add any additional information as you wish - homepage, logo, privacy policy, etc. None of this is required, but it may help your users.
+
+[reconfigure]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
diff --git a/doc/integration/img/akismet_settings.png b/doc/integration/img/akismet_settings.png
index c2aa97b132e..689654bf960 100644
--- a/doc/integration/img/akismet_settings.png
+++ b/doc/integration/img/akismet_settings.png
Binary files differ
diff --git a/doc/integration/img/bitbucket_oauth_keys.png b/doc/integration/img/bitbucket_oauth_keys.png
index 3fb2f7524a3..6dd2c7d744e 100644
--- a/doc/integration/img/bitbucket_oauth_keys.png
+++ b/doc/integration/img/bitbucket_oauth_keys.png
Binary files differ
diff --git a/doc/integration/img/bitbucket_oauth_settings_page.png b/doc/integration/img/bitbucket_oauth_settings_page.png
index a3047712d8c..3e6dea6cfe9 100644
--- a/doc/integration/img/bitbucket_oauth_settings_page.png
+++ b/doc/integration/img/bitbucket_oauth_settings_page.png
Binary files differ
diff --git a/doc/integration/img/enabled-oauth-sign-in-sources.png b/doc/integration/img/enabled-oauth-sign-in-sources.png
index b23d6dcc595..f145aeae75c 100644
--- a/doc/integration/img/enabled-oauth-sign-in-sources.png
+++ b/doc/integration/img/enabled-oauth-sign-in-sources.png
Binary files differ
diff --git a/doc/integration/img/facebook_api_keys.png b/doc/integration/img/facebook_api_keys.png
index 995845d5a69..9463ec1e7a3 100644
--- a/doc/integration/img/facebook_api_keys.png
+++ b/doc/integration/img/facebook_api_keys.png
Binary files differ
diff --git a/doc/integration/img/facebook_app_settings.png b/doc/integration/img/facebook_app_settings.png
index 1cd586ecd7c..81f38cab16e 100644
--- a/doc/integration/img/facebook_app_settings.png
+++ b/doc/integration/img/facebook_app_settings.png
Binary files differ
diff --git a/doc/integration/img/facebook_website_url.png b/doc/integration/img/facebook_website_url.png
index 10e1bd5d5a6..67d78d13951 100644
--- a/doc/integration/img/facebook_website_url.png
+++ b/doc/integration/img/facebook_website_url.png
Binary files differ
diff --git a/doc/integration/img/github_app.png b/doc/integration/img/github_app.png
index de31242679a..d6c289a1de1 100644
--- a/doc/integration/img/github_app.png
+++ b/doc/integration/img/github_app.png
Binary files differ
diff --git a/doc/integration/img/gitlab_app.png b/doc/integration/img/gitlab_app.png
index 065316fd3c7..b4958581a9b 100644
--- a/doc/integration/img/gitlab_app.png
+++ b/doc/integration/img/gitlab_app.png
Binary files differ
diff --git a/doc/integration/img/gmail_action_buttons_for_gitlab.png b/doc/integration/img/gmail_action_buttons_for_gitlab.png
index a6704139091..0e3e24d6ffc 100644
--- a/doc/integration/img/gmail_action_buttons_for_gitlab.png
+++ b/doc/integration/img/gmail_action_buttons_for_gitlab.png
Binary files differ
diff --git a/doc/integration/img/google_app.png b/doc/integration/img/google_app.png
index 08f7f714553..9fda06dabb1 100644
--- a/doc/integration/img/google_app.png
+++ b/doc/integration/img/google_app.png
Binary files differ
diff --git a/doc/integration/img/oauth_provider_admin_application.png b/doc/integration/img/oauth_provider_admin_application.png
index fc5f7596fcc..c8ecce129c8 100644
--- a/doc/integration/img/oauth_provider_admin_application.png
+++ b/doc/integration/img/oauth_provider_admin_application.png
Binary files differ
diff --git a/doc/integration/img/oauth_provider_application_form.png b/doc/integration/img/oauth_provider_application_form.png
index 606ab3e3467..954681e054e 100644
--- a/doc/integration/img/oauth_provider_application_form.png
+++ b/doc/integration/img/oauth_provider_application_form.png
Binary files differ
diff --git a/doc/integration/img/oauth_provider_application_id_secret.png b/doc/integration/img/oauth_provider_application_id_secret.png
index cbedcef8376..65cca5f1e1b 100644
--- a/doc/integration/img/oauth_provider_application_id_secret.png
+++ b/doc/integration/img/oauth_provider_application_id_secret.png
Binary files differ
diff --git a/doc/integration/img/oauth_provider_authorized_application.png b/doc/integration/img/oauth_provider_authorized_application.png
index 6a2ea09073c..ed99db3476d 100644
--- a/doc/integration/img/oauth_provider_authorized_application.png
+++ b/doc/integration/img/oauth_provider_authorized_application.png
Binary files differ
diff --git a/doc/integration/img/oauth_provider_user_wide_applications.png b/doc/integration/img/oauth_provider_user_wide_applications.png
index 0c7b095a2dd..9cc12555574 100644
--- a/doc/integration/img/oauth_provider_user_wide_applications.png
+++ b/doc/integration/img/oauth_provider_user_wide_applications.png
Binary files differ
diff --git a/doc/integration/img/spam_log.png b/doc/integration/img/spam_log.png
index 8d574448690..43e267daff4 100644
--- a/doc/integration/img/spam_log.png
+++ b/doc/integration/img/spam_log.png
Binary files differ
diff --git a/doc/integration/img/submit_issue.png b/doc/integration/img/submit_issue.png
index 5c7896a7eec..8accb78faf3 100644
--- a/doc/integration/img/submit_issue.png
+++ b/doc/integration/img/submit_issue.png
Binary files differ
diff --git a/doc/integration/img/twitter_app_api_keys.png b/doc/integration/img/twitter_app_api_keys.png
index 15b29ac7d16..34e3c3ba001 100644
--- a/doc/integration/img/twitter_app_api_keys.png
+++ b/doc/integration/img/twitter_app_api_keys.png
Binary files differ
diff --git a/doc/integration/img/twitter_app_details.png b/doc/integration/img/twitter_app_details.png
index 323112a88bb..b53f4eb3202 100644
--- a/doc/integration/img/twitter_app_details.png
+++ b/doc/integration/img/twitter_app_details.png
Binary files differ
diff --git a/doc/integration/jira.md b/doc/integration/jira.md
index 78aa6634116..b6923f74e28 100644
--- a/doc/integration/jira.md
+++ b/doc/integration/jira.md
@@ -1,3 +1 @@
-# GitLab JIRA integration
-
-This document was moved under [project_services/jira](../project_services/jira.md).
+This document was moved to [integrations/jira](../user/project/integrations/jira.md).
diff --git a/doc/integration/ldap.md b/doc/integration/ldap.md
index 30f0c15dacc..242890af981 100644
--- a/doc/integration/ldap.md
+++ b/doc/integration/ldap.md
@@ -1,3 +1 @@
-# GitLab LDAP integration
-
-This document was moved under [`administration/auth/ldap`](../administration/auth/ldap.md).
+This document was moved to [`administration/auth/ldap`](../administration/auth/ldap.md).
diff --git a/doc/integration/oauth2_generic.md b/doc/integration/oauth2_generic.md
new file mode 100644
index 00000000000..e71706fef7d
--- /dev/null
+++ b/doc/integration/oauth2_generic.md
@@ -0,0 +1,65 @@
+# Sign into GitLab with (almost) any OAuth2 provider
+
+The `omniauth-oauth2-generic` gem allows Single Sign On between GitLab and your own OAuth2 provider
+(or any OAuth2 provider compatible with this gem)
+
+This strategy is designed to allow configuration of the simple OmniAuth SSO process outlined below:
+
+1. Strategy directs client to your authorization URL (**configurable**), with specified ID and key
+1. OAuth provider handles authentication of request, user, and (optionally) authorization to access user's profile
+1. OAuth provider directs client back to GitLab where Strategy handles retrieval of access token
+1. Strategy requests user information from a **configurable** "user profile" URL (using the access token)
+1. Strategy parses user information from the response, using a **configurable** format
+1. GitLab finds or creates the returned user and logs them in
+
+### Limitations of this Strategy:
+
+- It can only be used for Single Sign on, and will not provide any other access granted by any OAuth provider
+ (importing projects or users, etc)
+- It only supports the Authorization Grant flow (most common for client-server applications, like GitLab)
+- It is not able to fetch user information from more than one URL
+- It has not been tested with user information formats other than JSON
+
+### Config Instructions
+
+1. Register your application in the OAuth2 provider you wish to authenticate with.
+
+ The redirect URI you provide when registering the application should be:
+
+ ```
+ http://your-gitlab.host.com/users/auth/oauth2_generic/callback
+ ```
+
+1. You should now be able to get a Client ID and Client Secret.
+ Where this shows up will differ for each provider.
+ This may also be called Application ID and Secret
+
+1. On your GitLab server, open the configuration file.
+
+ For Omnibus package:
+
+ ```sh
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
+
+ For installations from source:
+
+ ```sh
+ cd /home/git/gitlab
+ sudo -u git -H editor config/gitlab.yml
+ ```
+
+1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings
+
+1. Add the provider-specific configuration for your provider, as [described in the gem's README][1]
+
+1. Save the configuration file
+
+1. Restart GitLab for the changes to take effect
+
+On the sign in page there should now be a new button below the regular sign in form.
+Click the button to begin your provider's authentication process. This will direct
+the browser to your OAuth2 Provider's authentication page. If everything goes well
+the user will be returned to your GitLab instance and will be signed in.
+
+[1]: https://gitlab.com/satorix/omniauth-oauth2-generic#gitlab-config-example \ No newline at end of file
diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md
index 0c53584d201..af8a1c4e5ed 100644
--- a/doc/integration/oauth_provider.md
+++ b/doc/integration/oauth_provider.md
@@ -74,8 +74,10 @@ in the **Authorized applications** section under **Profile Settings > Applicatio
---
-As you can see, the default scope `api` is used, which is the only scope that
-GitLab supports so far. At any time you can revoke any access by just clicking
-**Revoke**.
+GitLab's OAuth applications support scopes, which allow various actions that any given
+application can perform. Although there are only two scopes available at the
+moment – `read_user` and `api` – the groundwork has been laid to add more scopes easily.
+
+At any time you can revoke any access by just clicking **Revoke**.
[oauth]: http://oauth.net/2/ "OAuth website"
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index 8a55fce96fe..6c11f46a70a 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -27,9 +27,11 @@ contains some settings that are common for all providers.
- [Twitter](twitter.md)
- [Shibboleth](shibboleth.md)
- [SAML](saml.md)
-- [Crowd](crowd.md)
+- [Crowd](../administration/auth/crowd.md)
- [Azure](azure.md)
- [Auth0](auth0.md)
+- [Authentiq](../administration/auth/authentiq.md)
+- [OAuth2Generic](oauth2_generic.md)
## Initial OmniAuth Configuration
@@ -40,6 +42,9 @@ that are in common for all providers that we need to consider.
- `allow_single_sign_on` allows you to specify the providers you want to allow to
automatically create an account. It defaults to `false`. If `false` users must
be created manually or they will not be able to sign in via OmniAuth.
+- `auto_link_ldap_user` can be used if you have [LDAP / ActiveDirectory](ldap.md)
+ integration enabled. It defaults to false. When enabled, users automatically
+ created through OmniAuth will be linked to their LDAP entry as well.
- `block_auto_created_users` defaults to `true`. If `true` auto created users will
be blocked by default and will have to be unblocked by an administrator before
they are able to sign in.
@@ -51,6 +56,10 @@ SAML, Shibboleth, Crowd or Google, or set it to `false` otherwise any user on
the Internet will be able to successfully sign in to your GitLab without
administrative approval.
+>**Note:**
+`auto_link_ldap_user` requires the `uid` of the user to be the same in both LDAP
+and the OmniAuth provider.
+
To change these settings:
* **For omnibus package**
@@ -71,6 +80,7 @@ To change these settings:
# using an array, e.g. ["saml", "twitter"], or as true/false to allow all providers or none.
# User accounts will be created automatically when authentication was successful.
gitlab_rails['omniauth_allow_single_sign_on'] = ['saml', 'twitter']
+ gitlab_rails['omniauth_auto_link_ldap_user'] = true
gitlab_rails['omniauth_block_auto_created_users'] = true
```
@@ -98,6 +108,8 @@ To change these settings:
# User accounts will be created automatically when authentication was successful.
allow_single_sign_on: ["saml", "twitter"]
+ auto_link_ldap_user: true
+
# Locks down those users until they have been cleared by the admin (default: true).
block_auto_created_users: true
```
diff --git a/doc/integration/openid_connect_provider.md b/doc/integration/openid_connect_provider.md
new file mode 100644
index 00000000000..56f367d841e
--- /dev/null
+++ b/doc/integration/openid_connect_provider.md
@@ -0,0 +1,47 @@
+# GitLab as OpenID Connect identity provider
+
+This document is about using GitLab as an OpenID Connect identity provider
+to sign in to other services.
+
+## Introduction to OpenID Connect
+
+[OpenID Connect] \(OIC) is a simple identity layer on top of the
+OAuth 2.0 protocol. It allows clients to verify the identity of the end-user
+based on the authentication performed by GitLab, as well as to obtain
+basic profile information about the end-user in an interoperable and
+REST-like manner. OIC performs many of the same tasks as OpenID 2.0,
+but does so in a way that is API-friendly, and usable by native and
+mobile applications.
+
+On the client side, you can use [omniauth-openid-connect] for Rails
+applications, or any of the other available [client implementations].
+
+GitLab's implementation uses the [doorkeeper-openid_connect] gem, refer
+to its README for more details about which parts of the specifications
+are supported.
+
+## Enabling OpenID Connect for OAuth applications
+
+Refer to the [OAuth guide] for basic information on how to set up OAuth
+applications in GitLab. To enable OIC for an application, all you have to do
+is select the `openid` scope in the application settings.
+
+Currently the following user information is shared with clients:
+
+| Claim | Type | Description |
+|:-----------------|:----------|:------------|
+| `sub` | `string` | An opaque token that uniquely identifies the user
+| `auth_time` | `integer` | The timestamp for the user's last authentication
+| `name` | `string` | The user's full name
+| `nickname` | `string` | The user's GitLab username
+| `email` | `string` | The user's public email address
+| `email_verified` | `boolean` | Whether the user's public email address was verified
+| `website` | `string` | URL for the user's website
+| `profile` | `string` | URL for the user's GitLab profile
+| `picture` | `string` | URL for the user's GitLab avatar
+
+[OpenID Connect]: http://openid.net/connect/ "OpenID Connect website"
+[doorkeeper-openid_connect]: https://github.com/doorkeeper-gem/doorkeeper-openid_connect "Doorkeeper::OpenidConnect website"
+[OAuth guide]: oauth_provider.md "GitLab as OAuth2 authentication service provider"
+[omniauth-openid-connect]: https://github.com/jjbohn/omniauth-openid-connect/ "OmniAuth::OpenIDConnect website"
+[client implementations]: http://openid.net/developers/libraries#connect "List of available client implementations"
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index f3b2a288776..b5b245c626f 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -74,7 +74,7 @@ in your SAML IdP:
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
},
label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
}
@@ -91,7 +91,7 @@ in your SAML IdP:
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
},
label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
}
@@ -109,7 +109,8 @@ in your SAML IdP:
1. Change the value of `issuer` to a unique name, which will identify the application
to the IdP.
-1. Restart GitLab for the changes to take effect.
+1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you
+ installed GitLab via Omnibus or from source respectively.
1. Register the GitLab SP in your SAML 2.0 IdP, using the application name specified
in `issuer`.
@@ -171,7 +172,7 @@ tell GitLab which groups are external via the `external_groups:` element:
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
} }
```
@@ -200,6 +201,9 @@ Please keep in mind that every sign in attempt will be redirected to the SAML se
so you will not be able to sign in using local credentials. Make sure that at least one
of the SAML users has admin permissions.
+You may also bypass the auto signin feature by browsing to
+https://gitlab.example.com/users/sign_in?auto_sign_in=false.
+
### `attribute_statements`
>**Note:**
@@ -226,7 +230,7 @@ args: {
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
attribute_statements: { email: ['EmailAddress'] }
}
```
@@ -244,7 +248,7 @@ args: {
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
attribute_statements: { email: ['EmailAddress'] },
allowed_clock_drift: 1 # for one second clock drift
}
@@ -268,13 +272,20 @@ message `Can't verify CSRF token authenticity`. This means that there is an erro
the SAML request, but this error never reaches GitLab due to the CSRF check.
To bypass this you can add `skip_before_action :verify_authenticity_token` to the
-`omniauth_callbacks_controller.rb` file. This will allow the error to hit GitLab,
-where it can then be seen in the usual logs, or as a flash message in the login
-screen.
+`omniauth_callbacks_controller.rb` file immediately after the `class` line and
+comment out the `protect_from_forgery` line using a `#` then restart Unicorn. This
+will allow the error to hit GitLab, where it can then be seen in the usual logs,
+or as a flash message on the login screen.
+
+That file is located in `/opt/gitlab/embedded/service/gitlab-rails/app/controllers`
+for Omnibus installations and by default in `/home/git/gitlab/app/controllers` for
+installations from source. Restart Unicorn using the `sudo gitlab-ctl restart unicorn`
+command on Omnibus installations and `sudo service gitlab restart` on installations
+from source.
-That file is located at `/opt/gitlab/embedded/service/gitlab-rails/app/controllers`
-for Omnibus installations and by default on `/home/git/gitlab/app/controllers` for
-installations from source.
+You may also find the [SSO Tracer](https://addons.mozilla.org/en-US/firefox/addon/sso-tracer)
+(Firefox) and [SAML Chrome Panel](https://chrome.google.com/webstore/detail/saml-chrome-panel/paijfdbeoenhembfhkhllainmocckace)
+(Chrome) browser extensions useful in your debugging.
### Invalid audience
@@ -307,3 +318,6 @@ For this you need take the following into account:
Make sure that one of the above described scenarios is valid, or the requests will
fail with one of the mentioned errors.
+
+[reconfigure]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
diff --git a/doc/integration/shibboleth.md b/doc/integration/shibboleth.md
index 5210ce0de9a..e0fc1bb801f 100644
--- a/doc/integration/shibboleth.md
+++ b/doc/integration/shibboleth.md
@@ -2,7 +2,7 @@
This documentation is for enabling shibboleth with omnibus-gitlab package.
-In order to enable Shibboleth support in gitlab we need to use Apache instead of Nginx (It may be possible to use Nginx, however this is difficult to configure using the bundled NIGNX provided in the omnibus-gitlab package). Apache uses mod_shib2 module for shibboleth authentication and can pass attributes as headers to omniauth-shibboleth provider.
+In order to enable Shibboleth support in gitlab we need to use Apache instead of Nginx (It may be possible to use Nginx, however this is difficult to configure using the bundled Nginx provided in the omnibus-gitlab package). Apache uses mod_shib2 module for shibboleth authentication and can pass attributes as headers to omniauth-shibboleth provider.
To enable the Shibboleth OmniAuth provider you must:
@@ -10,7 +10,7 @@ To enable the Shibboleth OmniAuth provider you must:
1. Configure Apache shibboleth module. Installation and configuration of module it self is out of scope of this document.
Check https://wiki.shibboleth.net/ for more info.
-1. You can find Apache config in gitlab-recipes (https://github.com/gitlabhq/gitlab-recipes/blob/master/web-server/apache/gitlab-ssl.conf)
+1. You can find Apache config in gitlab-recipes (https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache)
Following changes are needed to enable shibboleth:
@@ -70,10 +70,9 @@ gitlab_rails['omniauth_providers'] = [
]
```
-1. Save changes and reconfigure gitlab:
-```
-sudo gitlab-ctl reconfigure
-```
+
+1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you
+ installed GitLab via Omnibus or from source respectively.
On the sign in page there should now be a "Sign in with: Shibboleth" icon below the regular sign in form. Click the icon to begin the authentication process. You will be redirected to IdP server (Depends on your Shibboleth module configuration). If everything goes well the user will be returned to GitLab and will be signed in.
@@ -122,4 +121,7 @@ you will not get a shibboleth session!
RequestHeader set X_FORWARDED_PROTO 'https'
RequestHeader set X-Forwarded-Ssl on
-``` \ No newline at end of file
+```
+
+[reconfigure]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
diff --git a/doc/integration/slash_commands.md b/doc/integration/slash_commands.md
new file mode 100644
index 00000000000..5d880ba785c
--- /dev/null
+++ b/doc/integration/slash_commands.md
@@ -0,0 +1,14 @@
+# Slash Commands
+
+Slash commands in Mattermost and Slack allow you to control GitLab and view GitLab content right inside your chat client, without having to leave it. For Slack, this requires a [project service configuration](../user/project/integrations/slack_slash_commands.md). Simply type the command as a message in your chat client to activate it.
+
+Commands are scoped to a project, with a trigger term that is specified during configuration. (We suggest you use the project name as the trigger term for simplicty and clarity.) Taking the trigger term as `project-name`, the commands are:
+
+
+| Command | Effect |
+| ------- | ------ |
+| `/project-name help` | Shows all available slash commands |
+| `/project-name issue new <title> <shift+return> <description>` | Creates a new issue with title `<title>` and description `<description>` |
+| `/project-name issue show <id>` | Shows the issue with id `<id>` |
+| `/project-name issue search <query>` | Shows up to 5 issues matching `<query>` |
+| `/project-name deploy <from> to <to>` | Deploy from the `<from>` environment to the `<to>` environment |
diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md
index abbea09f22f..d0976b6201e 100644
--- a/doc/integration/twitter.md
+++ b/doc/integration/twitter.md
@@ -74,6 +74,10 @@ To enable the Twitter OmniAuth provider you must register your application with
1. Save the configuration file.
-1. Restart GitLab for the changes to take effect.
+1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you
+ installed GitLab via Omnibus or from source respectively.
On the sign in page there should now be a Twitter icon below the regular sign in form. Click the icon to begin the authentication process. Twitter will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in.
+
+[reconfigure]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
diff --git a/doc/intro/README.md b/doc/intro/README.md
index 1790b2b761f..7485912d1a2 100644
--- a/doc/intro/README.md
+++ b/doc/intro/README.md
@@ -11,9 +11,9 @@ Create projects and groups.
Create issues, labels, milestones, cast your vote, and review issues.
-- [Create a new issue](../gitlab-basics/create-issue.md)
+- [Create a new issue](../user/project/issues/index.md#new-issue)
- [Assign labels to issues](../user/project/labels.md)
-- [Use milestones as an overview of your project's tracker](../workflow/milestones.md)
+- [Use milestones as an overview of your project's tracker](../user/project/milestones/index.md)
- [Use voting to express your like/dislike to issues and merge requests](../workflow/award_emoji.md)
## Collaborate
@@ -23,7 +23,7 @@ Create merge requests and review code.
- [Fork a project and contribute to it](../workflow/forking_workflow.md)
- [Create a new merge request](../gitlab-basics/add-merge-request.md)
- [Automatically close issues from merge requests](../user/project/issues/automatic_issue_closing.md)
-- [Automatically merge when your builds succeed](../user/project/merge_requests/merge_when_build_succeeds.md)
+- [Automatically merge when pipeline succeeds](../user/project/merge_requests/merge_when_pipeline_succeeds.md)
- [Revert any commit](../user/project/merge_requests/revert_changes.md)
- [Cherry-pick any commit](../user/project/merge_requests/cherry_pick_changes.md)
diff --git a/doc/migrate_ci_to_ce/README.md b/doc/migrate_ci_to_ce/README.md
index 8f9ef054949..2e7782736ff 100644
--- a/doc/migrate_ci_to_ce/README.md
+++ b/doc/migrate_ci_to_ce/README.md
@@ -1,4 +1,4 @@
-## Migrate GitLab CI to GitLab CE or EE
+# Migrate GitLab CI to GitLab CE or EE
Beginning with version 8.0 of GitLab Community Edition (CE) and Enterprise
Edition (EE), GitLab CI is no longer its own application, but is instead built
@@ -12,7 +12,7 @@ is not possible.**
We recommend that you read through the entire migration process in this
document before beginning.
-### Overview
+## Overview
In this document we assume you have a GitLab server and a GitLab CI server. It
does not matter if these are the same machine.
@@ -26,7 +26,7 @@ can be online for most of the procedure; the only GitLab downtime (if any) is
during the upgrade to 8.0. Your CI service will be offline from the moment you
upgrade to 8.0 until you finish the migration procedure.
-### Before upgrading
+## Before upgrading
If you have GitLab CI installed using omnibus-gitlab packages but **you don't want to migrate your existing data**:
@@ -38,12 +38,12 @@ run `sudo gitlab-ctl reconfigure` and you can reach CI at `gitlab.example.com/ci
If you want to migrate your existing data, continue reading.
-#### 0. Updating Omnibus from versions prior to 7.13
+### 0. Updating Omnibus from versions prior to 7.13
If you are updating from older versions you should first update to 7.14 and then to 8.0.
Otherwise it's pretty likely that you will encounter problems described in the [Troubleshooting](#troubleshooting).
-#### 1. Verify that backups work
+### 1. Verify that backups work
Make sure that the backup script on both servers can connect to the database.
@@ -73,7 +73,7 @@ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production SKIP=r
If this fails you need to fix it before upgrading to 8.0. Also see
https://about.gitlab.com/getting-help/
-#### 2. Check source and target database types
+### 2. Check source and target database types
Check what databases you use on your GitLab server and your CI server.
Look for the 'adapter:' line. If your CI server and your GitLab server use
@@ -102,7 +102,7 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
```
-#### 3. Storage planning
+### 3. Storage planning
Decide where to store CI build traces on GitLab server. GitLab CI uses
files on disk to store CI build traces. The default path for these build
@@ -111,34 +111,34 @@ traces is `/var/opt/gitlab/gitlab-ci/builds` (Omnibus) or
a special location, or if you are using NFS, you should make sure that you
store build traces on the same storage as your Git repositories.
-### I. Upgrading
+## I. Upgrading
From this point on, GitLab CI will be unavailable for your end users.
-#### 1. Upgrade GitLab to 8.0
+### 1. Upgrade GitLab to 8.0
First upgrade your GitLab server to version 8.0:
https://about.gitlab.com/update/
-#### 2. Disable CI on the GitLab server during the migration
+### 2. Disable CI on the GitLab server during the migration
After you update, go to the admin panel and temporarily disable CI. As
an administrator, go to **Admin Area** -> **Settings**, and under
**Continuous Integration** uncheck **Disable to prevent CI usage until rake
ci:migrate is run (8.0 only)**.
-#### 3. CI settings are now in GitLab
+### 3. CI settings are now in GitLab
If you want to use custom CI settings (e.g. change where builds are
stored), please update `/etc/gitlab/gitlab.rb` (Omnibus) or
`/home/git/gitlab/config/gitlab.yml` (Source).
-#### 4. Upgrade GitLab CI to 8.0
+### 4. Upgrade GitLab CI to 8.0
Now upgrade GitLab CI to version 8.0. If you are using Omnibus packages,
this may have already happened when you upgraded GitLab to 8.0.
-#### 5. Disable GitLab CI on the CI server
+### 5. Disable GitLab CI on the CI server
Disable GitLab CI after upgrading to 8.0.
@@ -154,9 +154,9 @@ cd /home/gitlab_ci/gitlab-ci
sudo -u gitlab_ci -H bundle exec whenever --clear-crontab RAILS_ENV=production
```
-### II. Moving data
+## II. Moving data
-#### 1. Database encryption key
+### 1. Database encryption key
Move the database encryption key from your CI server to your GitLab
server. The command below will show you what you need to copy-paste to your
@@ -174,7 +174,7 @@ cd /home/gitlab_ci/gitlab-ci
sudo -u gitlab_ci -H bundle exec rake backup:show_secrets RAILS_ENV=production
```
-#### 2. SQL data and build traces
+### 2. SQL data and build traces
Create your final CI data export. If you are converting from MySQL to
PostgreSQL, add ` MYSQL_TO_POSTGRESQL=1` to the end of the rake command. When
@@ -192,7 +192,7 @@ cd /home/gitlab_ci/gitlab-ci
sudo -u gitlab_ci -H bundle exec rake backup:create RAILS_ENV=production
```
-#### 3. Copy data to the GitLab server
+### 3. Copy data to the GitLab server
If you were running GitLab and GitLab CI on the same server you can skip this
step.
@@ -209,7 +209,7 @@ ssh -A ci_admin@ci_server.example
scp /path/to/12345_gitlab_ci_backup.tar gitlab_admin@gitlab_server.example:~
```
-#### 4. Move data to the GitLab backups folder
+### 4. Move data to the GitLab backups folder
Make the CI data archive discoverable for GitLab. We assume below that you
store backups in the default path, adjust the command if necessary.
@@ -223,7 +223,7 @@ sudo mv /path/to/12345_gitlab_ci_backup.tar /var/opt/gitlab/backups/
sudo mv /path/to/12345_gitlab_ci_backup.tar /home/git/gitlab/tmp/backups/
```
-#### 5. Import the CI data into GitLab.
+### 5. Import the CI data into GitLab.
This step will delete any existing CI data on your GitLab server. There should
be no CI data yet because you turned CI on the GitLab server off earlier.
@@ -239,7 +239,7 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake ci:migrate RAILS_ENV=production
```
-#### 6. Restart GitLab
+### 6. Restart GitLab
```
# On your GitLab server:
@@ -251,7 +251,7 @@ sudo gitlab-ctl restart sidekiq
sudo service gitlab reload
```
-### III. Redirecting traffic
+## III. Redirecting traffic
If you were running GitLab CI with Omnibus packages and you were using the
internal NGINX configuration your CI service should now be available both at
@@ -261,7 +261,7 @@ If you installed GitLab CI from source we now need to configure a redirect in
NGINX so that existing CI runners can keep using the old CI server address, and
so that existing links to your CI server keep working.
-#### 1. Update Nginx configuration
+### 1. Update Nginx configuration
To ensure that your existing CI runners are able to communicate with the
migrated installation, and that existing build triggers still work, you'll need
@@ -317,22 +317,22 @@ You should also make sure that you can:
1. `curl https://YOUR_GITLAB_SERVER_FQDN/` from your previous GitLab CI server.
1. `curl https://YOUR_CI_SERVER_FQDN/` from your GitLab CE (or EE) server.
-#### 2. Check Nginx configuration
+### 2. Check Nginx configuration
sudo nginx -t
-#### 3. Restart Nginx
+### 3. Restart Nginx
sudo /etc/init.d/nginx restart
-#### Restore from backup
+### Restore from backup
If something went wrong and you need to restore a backup, consult the [Backup
restoration](../raketasks/backup_restore.md) guide.
-### Troubleshooting
+## Troubleshooting
-#### show:secrets problem (Omnibus-only)
+### show:secrets problem (Omnibus-only)
If you see errors like this:
```
Missing `secret_key_base` or `db_key_base` for 'production' environment. The secrets will be generated and stored in `config/secrets.yml`
@@ -343,7 +343,7 @@ Errno::EACCES: Permission denied @ rb_sysopen - config/secrets.yml
This can happen if you are updating from versions prior to 7.13 straight to 8.0.
The fix for this is to update to Omnibus 7.14 first and then update it to 8.0.
-#### Permission denied when accessing /var/opt/gitlab/gitlab-ci/builds
+### Permission denied when accessing /var/opt/gitlab/gitlab-ci/builds
To fix that issue you have to change builds/ folder permission before doing final backup:
```
sudo chown -R gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds
@@ -354,7 +354,7 @@ Then before executing `ci:migrate` you need to fix builds folder permission:
sudo chown git:git /var/opt/gitlab/gitlab-ci/builds
```
-#### Problems when importing CI database to GitLab
+### Problems when importing CI database to GitLab
If you were migrating CI database from MySQL to PostgreSQL manually you can see errors during import about missing sequences:
```
ALTER SEQUENCE
diff --git a/doc/monitoring/health_check.md b/doc/monitoring/health_check.md
index eac57bc3de4..6cf93c33ec2 100644
--- a/doc/monitoring/health_check.md
+++ b/doc/monitoring/health_check.md
@@ -1,66 +1 @@
-# Health Check
-
-> [Introduced][ce-3888] in GitLab 8.8.
-
-GitLab provides a health check endpoint for uptime monitoring on the `health_check` web
-endpoint. The health check reports on the overall system status based on the status of
-the database connection, the state of the database migrations, and the ability to write
-and access the cache. This endpoint can be provided to uptime monitoring services like
-[Pingdom][pingdom], [Nagios][nagios-health], and [NewRelic][newrelic-health].
-
-## Access Token
-
-An access token needs to be provided while accessing the health check endpoint. The current
-accepted token can be found on the `admin/health_check` page of your GitLab instance.
-
-![access token](img/health_check_token.png)
-
-The access token can be passed as a URL parameter:
-
-```
-https://gitlab.example.com/health_check.json?token=ACCESS_TOKEN
-```
-
-or as an HTTP header:
-
-```bash
-curl --header "TOKEN: ACCESS_TOKEN" https://gitlab.example.com/health_check.json
-```
-
-## Using the Endpoint
-
-Once you have the access token, health information can be retrieved as plain text, JSON,
-or XML using the `health_check` endpoint:
-
-- `https://gitlab.example.com/health_check?token=ACCESS_TOKEN`
-- `https://gitlab.example.com/health_check.json?token=ACCESS_TOKEN`
-- `https://gitlab.example.com/health_check.xml?token=ACCESS_TOKEN`
-
-You can also ask for the status of specific services:
-
-- `https://gitlab.example.com/health_check/cache.json?token=ACCESS_TOKEN`
-- `https://gitlab.example.com/health_check/database.json?token=ACCESS_TOKEN`
-- `https://gitlab.example.com/health_check/migrations.json?token=ACCESS_TOKEN`
-
-For example, the JSON output of the following health check:
-
-```bash
-curl --header "TOKEN: ACCESS_TOKEN" https://gitlab.example.com/health_check.json
-```
-
-would be like:
-
-```
-{"healthy":true,"message":"success"}
-```
-
-## Status
-
-On failure, the endpoint will return a `500` HTTP status code. On success, the endpoint
-will return a valid successful HTTP status code, and a `success` message. Ideally your
-uptime monitoring should look for the success message.
-
-[ce-3888]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3888
-[pingdom]: https://www.pingdom.com
-[nagios-health]: https://nagios-plugins.org/doc/man/check_http.html
-[newrelic-health]: https://docs.newrelic.com/docs/alerts/alert-policies/downtime-alerts/availability-monitoring
+This document was moved to [user/admin_area/monitoring/health_check](../user/admin_area/monitoring/health_check.md).
diff --git a/doc/monitoring/img/health_check_token.png b/doc/monitoring/img/health_check_token.png
deleted file mode 100644
index 2d7c82a65a8..00000000000
--- a/doc/monitoring/img/health_check_token.png
+++ /dev/null
Binary files differ
diff --git a/doc/monitoring/performance/gitlab_configuration.md b/doc/monitoring/performance/gitlab_configuration.md
index 771584268d9..19d46135930 100644
--- a/doc/monitoring/performance/gitlab_configuration.md
+++ b/doc/monitoring/performance/gitlab_configuration.md
@@ -1,40 +1 @@
-# GitLab Configuration
-
-GitLab Performance Monitoring is disabled by default. To enable it and change any of its
-settings, navigate to the Admin area in **Settings > Metrics**
-(`/admin/application_settings`).
-
-The minimum required settings you need to set are the InfluxDB host and port.
-Make sure _Enable InfluxDB Metrics_ is checked and hit **Save** to save the
-changes.
-
----
-
-![GitLab Performance Monitoring Admin Settings](img/metrics_gitlab_configuration_settings.png)
-
----
-
-Finally, a restart of all GitLab processes is required for the changes to take
-effect:
-
-```bash
-# For Omnibus installations
-sudo gitlab-ctl restart
-
-# For installations from source
-sudo service gitlab restart
-```
-
-## Pending Migrations
-
-When any migrations are pending, the metrics are disabled until the migrations
-have been performed.
-
----
-
-Read more on:
-
-- [Introduction to GitLab Performance Monitoring](introduction.md)
-- [InfluxDB Configuration](influxdb_configuration.md)
-- [InfluxDB Schema](influxdb_schema.md)
-- [Grafana Install/Configuration](grafana_configuration.md)
+This document was moved to [administration/monitoring/performance/gitlab_configuration](../../administration/monitoring/performance/gitlab_configuration.md).
diff --git a/doc/monitoring/performance/grafana_configuration.md b/doc/monitoring/performance/grafana_configuration.md
index 7947b0fedc4..0d4be02ff5f 100644
--- a/doc/monitoring/performance/grafana_configuration.md
+++ b/doc/monitoring/performance/grafana_configuration.md
@@ -1,111 +1 @@
-# Grafana Configuration
-
-[Grafana](http://grafana.org/) is a tool that allows you to visualize time
-series metrics through graphs and dashboards. It supports several backend
-data stores, including InfluxDB. GitLab writes performance data to InfluxDB
-and Grafana will allow you to query InfluxDB to display useful graphs.
-
-For the easiest installation and configuration, install Grafana on the same
-server as InfluxDB. For larger installations, you may want to split out these
-services.
-
-## Installation
-
-Grafana supplies package repositories (Yum/Apt) for easy installation.
-See [Grafana installation documentation](http://docs.grafana.org/installation/)
-for detailed steps.
-
-> **Note**: Before starting Grafana for the first time, set the admin user
-and password in `/etc/grafana/grafana.ini`. Otherwise, the default password
-will be `admin`.
-
-## Configuration
-
-Login as the admin user. Expand the menu by clicking the Grafana logo in the
-top left corner. Choose 'Data Sources' from the menu. Then, click 'Add new'
-in the top bar.
-
-![Grafana empty data source page](img/grafana_data_source_empty.png)
-
-Fill in the configuration details for the InfluxDB data source. Save and
-Test Connection to ensure the configuration is correct.
-
-- **Name**: InfluxDB
-- **Default**: Checked
-- **Type**: InfluxDB 0.9.x (Even if you're using InfluxDB 0.10.x)
-- **Url**: https://localhost:8086 (Or the remote URL if you've installed InfluxDB
-on a separate server)
-- **Access**: proxy
-- **Database**: gitlab
-- **User**: admin (Or the username configured when setting up InfluxDB)
-- **Password**: The password configured when you set up InfluxDB
-
-![Grafana data source configurations](img/grafana_data_source_configuration.png)
-
-## Apply retention policies and create continuous queries
-
-If you intend to import the GitLab provided Grafana dashboards, you will need to
-set up the right retention policies and continuous queries. The easiest way of
-doing this is by using the [influxdb-management](https://gitlab.com/gitlab-org/influxdb-management)
-repository.
-
-To use this repository you must first clone it:
-
-```
-git clone https://gitlab.com/gitlab-org/influxdb-management.git
-cd influxdb-management
-```
-
-Next you must install the required dependencies:
-
-```
-gem install bundler
-bundle install
-```
-
-Now you must configure the repository by first copying `.env.example` to `.env`
-and then editing the `.env` file to contain the correct InfluxDB settings. Once
-configured you can simply run `bundle exec rake` and the InfluxDB database will
-be configured for you.
-
-For more information see the [influxdb-management README](https://gitlab.com/gitlab-org/influxdb-management/blob/master/README.md).
-
-## Import Dashboards
-
-You can now import a set of default dashboards that will give you a good
-start on displaying useful information. GitLab has published a set of default
-[Grafana dashboards][grafana-dashboards] to get you started. Clone the
-repository or download a zip/tarball, then follow these steps to import each
-JSON file.
-
-Open the dashboard dropdown menu and click 'Import'
-
-![Grafana dashboard dropdown](img/grafana_dashboard_dropdown.png)
-
-Click 'Choose file' and browse to the location where you downloaded or cloned
-the dashboard repository. Pick one of the JSON files to import.
-
-![Grafana dashboard import](img/grafana_dashboard_import.png)
-
-Once the dashboard is imported, be sure to click save icon in the top bar. If
-you do not save the dashboard after importing it will be removed when you
-navigate away.
-
-![Grafana save icon](img/grafana_save_icon.png)
-
-Repeat this process for each dashboard you wish to import.
-
-Alternatively you can automatically import all the dashboards into your Grafana
-instance. See the README of the [Grafana dashboards][grafana-dashboards]
-repository for more information on this process.
-
-[grafana-dashboards]: https://gitlab.com/gitlab-org/grafana-dashboards
-
----
-
-Read more on:
-
-- [Introduction to GitLab Performance Monitoring](introduction.md)
-- [GitLab Configuration](gitlab_configuration.md)
-- [InfluxDB Installation/Configuration](influxdb_configuration.md)
-- [InfluxDB Schema](influxdb_schema.md)
+This document was moved to [administration/monitoring/performance/grafana_configuration](../../administration/monitoring/performance/grafana_configuration.md).
diff --git a/doc/monitoring/performance/img/grafana_dashboard_dropdown.png b/doc/monitoring/performance/img/grafana_dashboard_dropdown.png
index 7e34fad71ce..51eef90068d 100644
--- a/doc/monitoring/performance/img/grafana_dashboard_dropdown.png
+++ b/doc/monitoring/performance/img/grafana_dashboard_dropdown.png
Binary files differ
diff --git a/doc/monitoring/performance/img/grafana_dashboard_import.png b/doc/monitoring/performance/img/grafana_dashboard_import.png
index f97624365c7..7761ea00522 100644
--- a/doc/monitoring/performance/img/grafana_dashboard_import.png
+++ b/doc/monitoring/performance/img/grafana_dashboard_import.png
Binary files differ
diff --git a/doc/monitoring/performance/img/grafana_data_source_configuration.png b/doc/monitoring/performance/img/grafana_data_source_configuration.png
index 7d50e4c88c2..3e749eb8f9d 100644
--- a/doc/monitoring/performance/img/grafana_data_source_configuration.png
+++ b/doc/monitoring/performance/img/grafana_data_source_configuration.png
Binary files differ
diff --git a/doc/monitoring/performance/img/grafana_data_source_empty.png b/doc/monitoring/performance/img/grafana_data_source_empty.png
index aa39a53acae..33fcaaaef64 100644
--- a/doc/monitoring/performance/img/grafana_data_source_empty.png
+++ b/doc/monitoring/performance/img/grafana_data_source_empty.png
Binary files differ
diff --git a/doc/monitoring/performance/img/grafana_save_icon.png b/doc/monitoring/performance/img/grafana_save_icon.png
index c740e33cd1c..c18f2147e9d 100644
--- a/doc/monitoring/performance/img/grafana_save_icon.png
+++ b/doc/monitoring/performance/img/grafana_save_icon.png
Binary files differ
diff --git a/doc/monitoring/performance/img/metrics_gitlab_configuration_settings.png b/doc/monitoring/performance/img/metrics_gitlab_configuration_settings.png
index e6ed45a0386..d96a18ebc04 100644
--- a/doc/monitoring/performance/img/metrics_gitlab_configuration_settings.png
+++ b/doc/monitoring/performance/img/metrics_gitlab_configuration_settings.png
Binary files differ
diff --git a/doc/monitoring/performance/influxdb_configuration.md b/doc/monitoring/performance/influxdb_configuration.md
index c30cd2950d8..15fd275e916 100644
--- a/doc/monitoring/performance/influxdb_configuration.md
+++ b/doc/monitoring/performance/influxdb_configuration.md
@@ -1,193 +1 @@
-# InfluxDB Configuration
-
-The default settings provided by [InfluxDB] are not sufficient for a high traffic
-GitLab environment. The settings discussed in this document are based on the
-settings GitLab uses for GitLab.com, depending on your own needs you may need to
-further adjust them.
-
-If you are intending to run InfluxDB on the same server as GitLab, make sure
-you have plenty of RAM since InfluxDB can use quite a bit depending on traffic.
-
-Unless you are going with a budget setup, it's advised to run it separately.
-
-## Requirements
-
-- InfluxDB 0.9.5 or newer
-- A fairly modern version of Linux
-- At least 4GB of RAM
-- At least 10GB of storage for InfluxDB data
-
-Note that the RAM and storage requirements can differ greatly depending on the
-amount of data received/stored. To limit the amount of stored data users can
-look into [InfluxDB Retention Policies][influxdb-retention].
-
-## Installation
-
-Installing InfluxDB is out of the scope of this document. Please refer to the
-[InfluxDB documentation].
-
-## InfluxDB Server Settings
-
-Since InfluxDB has many settings that users may wish to customize themselves
-(e.g. what port to run InfluxDB on), we'll only cover the essentials.
-
-The configuration file in question is usually located at
-`/etc/influxdb/influxdb.conf`. Whenever you make a change in this file,
-InfluxDB needs to be restarted.
-
-### Storage Engine
-
-InfluxDB comes with different storage engines and as of InfluxDB 0.9.5 a new
-storage engine is available, called [TSM Tree]. All users **must** use the new
-`tsm1` storage engine as this [will be the default engine][tsm1-commit] in
-upcoming InfluxDB releases.
-
-Make sure you have the following in your configuration file:
-
-```
-[data]
- dir = "/var/lib/influxdb/data"
- engine = "tsm1"
-```
-
-### Admin Panel
-
-Production environments should have the InfluxDB admin panel **disabled**. This
-feature can be disabled by adding the following to your InfluxDB configuration
-file:
-
-```
-[admin]
- enabled = false
-```
-
-### HTTP
-
-HTTP is required when using the [InfluxDB CLI] or other tools such as Grafana,
-thus it should be enabled. When enabling make sure to _also_ enable
-authentication:
-
-```
-[http]
- enabled = true
- auth-enabled = true
-```
-
-_**Note:** Before you enable authentication, you might want to [create an
-admin user](#create-a-new-admin-user)._
-
-### UDP
-
-GitLab writes data to InfluxDB via UDP and thus this must be enabled. Enabling
-UDP can be done using the following settings:
-
-```
-[[udp]]
- enabled = true
- bind-address = ":8089"
- database = "gitlab"
- batch-size = 1000
- batch-pending = 5
- batch-timeout = "1s"
- read-buffer = 209715200
-```
-
-This does the following:
-
-1. Enable UDP and bind it to port 8089 for all addresses.
-2. Store any data received in the "gitlab" database.
-3. Define a batch of points to be 1000 points in size and allow a maximum of
- 5 batches _or_ flush them automatically after 1 second.
-4. Define a UDP read buffer size of 200 MB.
-
-One of the most important settings here is the UDP read buffer size as if this
-value is set too low, packets will be dropped. You must also make sure the OS
-buffer size is set to the same value, the default value is almost never enough.
-
-To set the OS buffer size to 200 MB, on Linux you can run the following command:
-
-```bash
-sysctl -w net.core.rmem_max=209715200
-```
-
-To make this permanent, add the following to `/etc/sysctl.conf` and restart the
-server:
-
-```bash
-net.core.rmem_max=209715200
-```
-
-It is **very important** to make sure the buffer sizes are large enough to
-handle all data sent to InfluxDB as otherwise you _will_ lose data. The above
-buffer sizes are based on the traffic for GitLab.com. Depending on the amount of
-traffic, users may be able to use a smaller buffer size, but we highly recommend
-using _at least_ 100 MB.
-
-When enabling UDP, users should take care to not expose the port to the public,
-as doing so will allow anybody to write data into your InfluxDB database (as
-[InfluxDB's UDP protocol][udp] doesn't support authentication). We recommend either
-whitelisting the allowed IP addresses/ranges, or setting up a VLAN and only
-allowing traffic from members of said VLAN.
-
-## Create a new admin user
-
-If you want to [enable authentication](#http), you might want to [create an
-admin user][influx-admin]:
-
-```
-influx -execute "CREATE USER jeff WITH PASSWORD '1234' WITH ALL PRIVILEGES"
-```
-
-## Create the `gitlab` database
-
-Once you get InfluxDB up and running, you need to create a database for GitLab.
-Make sure you have changed the [storage engine](#storage-engine) to `tsm1`
-before creating a database.
-
-_**Note:** If you [created an admin user](#create-a-new-admin-user) and enabled
-[HTTP authentication](#http), remember to append the username (`-username <username>`)
-and password (`-password <password>`) you set earlier to the commands below._
-
-Run the following command to create a database named `gitlab`:
-
-```bash
-influx -execute 'CREATE DATABASE gitlab'
-```
-
-The name **must** be `gitlab`, do not use any other name.
-
-Next, make sure that the database was successfully created:
-
-```bash
-influx -execute 'SHOW DATABASES'
-```
-
-The output should be similar to:
-
-```
-name: databases
----------------
-name
-_internal
-gitlab
-```
-
-That's it! Now your GitLab instance should send data to InfluxDB.
-
----
-
-Read more on:
-
-- [Introduction to GitLab Performance Monitoring](introduction.md)
-- [GitLab Configuration](gitlab_configuration.md)
-- [InfluxDB Schema](influxdb_schema.md)
-- [Grafana Install/Configuration](grafana_configuration.md)
-
-[influxdb-retention]: https://docs.influxdata.com/influxdb/v0.9/query_language/database_management/#retention-policy-management
-[influxdb documentation]: https://docs.influxdata.com/influxdb/v0.9/
-[influxdb cli]: https://docs.influxdata.com/influxdb/v0.9/tools/shell/
-[udp]: https://docs.influxdata.com/influxdb/v0.9/write_protocols/udp/
-[influxdb]: https://influxdata.com/time-series-platform/influxdb/
-[tsm tree]: https://influxdata.com/blog/new-storage-engine-time-structured-merge-tree/
-[tsm1-commit]: https://github.com/influxdata/influxdb/commit/15d723dc77651bac83e09e2b1c94be480966cb0d
-[influx-admin]: https://docs.influxdata.com/influxdb/v0.9/administration/authentication_and_authorization/#create-a-new-admin-user
+This document was moved to [administration/monitoring/performance/influxdb_configuration](../../administration/monitoring/performance/influxdb_configuration.md).
diff --git a/doc/monitoring/performance/influxdb_schema.md b/doc/monitoring/performance/influxdb_schema.md
index eff0e29f58d..e53f9701dc3 100644
--- a/doc/monitoring/performance/influxdb_schema.md
+++ b/doc/monitoring/performance/influxdb_schema.md
@@ -1,97 +1 @@
-# InfluxDB Schema
-
-The following measurements are currently stored in InfluxDB:
-
-- `PROCESS_file_descriptors`
-- `PROCESS_gc_statistics`
-- `PROCESS_memory_usage`
-- `PROCESS_method_calls`
-- `PROCESS_object_counts`
-- `PROCESS_transactions`
-- `PROCESS_views`
-- `events`
-
-Here, `PROCESS` is replaced with either `rails` or `sidekiq` depending on the
-process type. In all series, any form of duration is stored in milliseconds.
-
-## PROCESS_file_descriptors
-
-This measurement contains the number of open file descriptors over time. The
-value field `value` contains the number of descriptors.
-
-## PROCESS_gc_statistics
-
-This measurement contains Ruby garbage collection statistics such as the amount
-of minor/major GC runs (relative to the last sampling interval), the time spent
-in garbage collection cycles, and all fields/values returned by `GC.stat`.
-
-## PROCESS_memory_usage
-
-This measurement contains the process' memory usage (in bytes) over time. The
-value field `value` contains the number of bytes.
-
-## PROCESS_method_calls
-
-This measurement contains the methods called during a transaction along with
-their duration, and a name of the transaction action that invoked the method (if
-available). The method call duration is stored in the value field `duration`,
-while the method name is stored in the tag `method`. The tag `action` contains
-the full name of the transaction action. Both the `method` and `action` fields
-are in the following format:
-
-```
-ClassName#method_name
-```
-
-For example, a method called by the `show` method in the `UsersController` class
-would have `action` set to `UsersController#show`.
-
-## PROCESS_object_counts
-
-This measurement is used to store retained Ruby objects (per class) and the
-amount of retained objects. The number of objects is stored in the `count` value
-field while the class name is stored in the `type` tag.
-
-## PROCESS_transactions
-
-This measurement is used to store basic transaction details such as the time it
-took to complete a transaction, how much time was spent in SQL queries, etc. The
-following value fields are available:
-
-| Value | Description |
-| ----- | ----------- |
-| `duration` | The total duration of the transaction |
-| `allocated_memory` | The amount of bytes allocated while the transaction was running. This value is only reliable when using single-threaded application servers |
-| `method_duration` | The total time spent in method calls |
-| `sql_duration` | The total time spent in SQL queries |
-| `view_duration` | The total time spent in views |
-
-## PROCESS_views
-
-This measurement is used to store view rendering timings for a transaction. The
-following value fields are available:
-
-| Value | Description |
-| ----- | ----------- |
-| `duration` | The rendering time of the view |
-| `view` | The path of the view, relative to the application's root directory |
-
-The `action` tag contains the action name of the transaction that rendered the
-view.
-
-## events
-
-This measurement is used to store generic events such as the number of Git
-pushes, Emails sent, etc. Each point in this measurement has a single value
-field called `count`. The value of this field is simply set to `1`. Each point
-also has at least one tag: `event`. This tag's value is set to the event name.
-Depending on the event type additional tags may be available as well.
-
----
-
-Read more on:
-
-- [Introduction to GitLab Performance Monitoring](introduction.md)
-- [GitLab Configuration](gitlab_configuration.md)
-- [InfluxDB Configuration](influxdb_configuration.md)
-- [Grafana Install/Configuration](grafana_configuration.md)
+This document was moved to [administration/monitoring/performance/influxdb_schema](../../administration/monitoring/performance/influxdb_schema.md).
diff --git a/doc/monitoring/performance/introduction.md b/doc/monitoring/performance/introduction.md
index 79904916b7e..ae88baa0c14 100644
--- a/doc/monitoring/performance/introduction.md
+++ b/doc/monitoring/performance/introduction.md
@@ -1,65 +1 @@
-# GitLab Performance Monitoring
-
-GitLab comes with its own application performance measuring system as of GitLab
-8.4, simply called "GitLab Performance Monitoring". GitLab Performance Monitoring is available in both the
-Community and Enterprise editions.
-
-Apart from this introduction, you are advised to read through the following
-documents in order to understand and properly configure GitLab Performance Monitoring:
-
-- [GitLab Configuration](gitlab_configuration.md)
-- [InfluxDB Install/Configuration](influxdb_configuration.md)
-- [InfluxDB Schema](influxdb_schema.md)
-- [Grafana Install/Configuration](grafana_configuration.md)
-
-## Introduction to GitLab Performance Monitoring
-
-GitLab Performance Monitoring makes it possible to measure a wide variety of statistics
-including (but not limited to):
-
-- The time it took to complete a transaction (a web request or Sidekiq job).
-- The time spent in running SQL queries and rendering HAML views.
-- The time spent executing (instrumented) Ruby methods.
-- Ruby object allocations, and retained objects in particular.
-- System statistics such as the process' memory usage and open file descriptors.
-- Ruby garbage collection statistics.
-
-Metrics data is written to [InfluxDB][influxdb] over [UDP][influxdb-udp]. Stored
-data can be visualized using [Grafana][grafana] or any other application that
-supports reading data from InfluxDB. Alternatively data can be queried using the
-InfluxDB CLI.
-
-## Metric Types
-
-Two types of metrics are collected:
-
-1. Transaction specific metrics.
-1. Sampled metrics, collected at a certain interval in a separate thread.
-
-### Transaction Metrics
-
-Transaction metrics are metrics that can be associated with a single
-transaction. This includes statistics such as the transaction duration, timings
-of any executed SQL queries, time spent rendering HAML views, etc. These metrics
-are collected for every Rack request and Sidekiq job processed.
-
-### Sampled Metrics
-
-Sampled metrics are metrics that can't be associated with a single transaction.
-Examples include garbage collection statistics and retained Ruby objects. These
-metrics are collected at a regular interval. This interval is made up out of two
-parts:
-
-1. A user defined interval.
-1. A randomly generated offset added on top of the interval, the same offset
- can't be used twice in a row.
-
-The actual interval can be anywhere between a half of the defined interval and a
-half above the interval. For example, for a user defined interval of 15 seconds
-the actual interval can be anywhere between 7.5 and 22.5. The interval is
-re-generated for every sampling run instead of being generated once and re-used
-for the duration of the process' lifetime.
-
-[influxdb]: https://influxdata.com/time-series-platform/influxdb/
-[influxdb-udp]: https://docs.influxdata.com/influxdb/v0.9/write_protocols/udp/
-[grafana]: http://grafana.org/
+This document was moved to [administration/monitoring/performance/introduction](../../administration/monitoring/performance/introduction.md).
diff --git a/doc/operations/README.md b/doc/operations/README.md
index 6a35dab7b6c..58f16aff7bd 100644
--- a/doc/operations/README.md
+++ b/doc/operations/README.md
@@ -1,5 +1 @@
-# GitLab operations
-
-- [Sidekiq MemoryKiller](sidekiq_memory_killer.md)
-- [Cleaning up Redis sessions](cleaning_up_redis_sessions.md)
-- [Understanding Unicorn and unicorn-worker-killer](unicorn.md)
+This document was moved to [administration/operations](../administration/operations.md).
diff --git a/doc/operations/cleaning_up_redis_sessions.md b/doc/operations/cleaning_up_redis_sessions.md
index 93521e976d5..2a1d0a8c8eb 100644
--- a/doc/operations/cleaning_up_redis_sessions.md
+++ b/doc/operations/cleaning_up_redis_sessions.md
@@ -1,52 +1 @@
-# Cleaning up stale Redis sessions
-
-Since version 6.2, GitLab stores web user sessions as key-value pairs in Redis.
-Prior to GitLab 7.3, user sessions did not automatically expire from Redis. If
-you have been running a large GitLab server (thousands of users) since before
-GitLab 7.3 we recommend cleaning up stale sessions to compact the Redis
-database after you upgrade to GitLab 7.3. You can also perform a cleanup while
-still running GitLab 7.2 or older, but in that case new stale sessions will
-start building up again after you clean up.
-
-In GitLab versions prior to 7.3.0, the session keys in Redis are 16-byte
-hexadecimal values such as '976aa289e2189b17d7ef525a6702ace9'. Starting with
-GitLab 7.3.0, the keys are
-prefixed with 'session:gitlab:', so they would look like
-'session:gitlab:976aa289e2189b17d7ef525a6702ace9'. Below we describe how to
-remove the keys in the old format.
-
-First we define a shell function with the proper Redis connection details.
-
-```
-rcli() {
- # This example works for Omnibus installations of GitLab 7.3 or newer. For an
- # installation from source you will have to change the socket path and the
- # path to redis-cli.
- sudo /opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.socket "$@"
-}
-
-# test the new shell function; the response should be PONG
-rcli ping
-```
-
-Now we do a search to see if there are any session keys in the old format for
-us to clean up.
-
-```
-# returns the number of old-format session keys in Redis
-rcli keys '*' | grep '^[a-f0-9]\{32\}$' | wc -l
-```
-
-If the number is larger than zero, you can proceed to expire the keys from
-Redis. If the number is zero there is nothing to clean up.
-
-```
-# Tell Redis to expire each matched key after 600 seconds.
-rcli keys '*' | grep '^[a-f0-9]\{32\}$' | awk '{ print "expire", $0, 600 }' | rcli
-# This will print '(integer) 1' for each key that gets expired.
-```
-
-Over the next 15 minutes (10 minutes expiry time plus 5 minutes Redis
-background save interval) your Redis database will be compacted. If you are
-still using GitLab 7.2, users who are not clicking around in GitLab during the
-10 minute expiry window will be signed out of GitLab.
+This document was moved to [administration/operations/cleaning_up_redis_sessions](../administration/operations/cleaning_up_redis_sessions.md).
diff --git a/doc/operations/moving_repositories.md b/doc/operations/moving_repositories.md
index 54adb99386a..c54bca324a5 100644
--- a/doc/operations/moving_repositories.md
+++ b/doc/operations/moving_repositories.md
@@ -1,180 +1 @@
-# Moving repositories managed by GitLab
-
-Sometimes you need to move all repositories managed by GitLab to
-another filesystem or another server. In this document we will look
-at some of the ways you can copy all your repositories from
-`/var/opt/gitlab/git-data/repositories` to `/mnt/gitlab/repositories`.
-
-We will look at three scenarios: the target directory is empty, the
-target directory contains an outdated copy of the repositories, and
-how to deal with thousands of repositories.
-
-**Each of the approaches we list can/will overwrite data in the
-target directory `/mnt/gitlab/repositories`. Do not mix up the
-source and the target.**
-
-## Target directory is empty: use a tar pipe
-
-If the target directory `/mnt/gitlab/repositories` is empty the
-simplest thing to do is to use a tar pipe. This method has low
-overhead and tar is almost always already installed on your system.
-However, it is not possible to resume an interrupted tar pipe: if
-that happens then all data must be copied again.
-
-```
-# As the git user
-tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
- tar -C /mnt/gitlab/repositories -xf -
-```
-
-If you want to see progress, replace `-xf` with `-xvf`.
-
-### Tar pipe to another server
-
-You can also use a tar pipe to copy data to another server. If your
-'git' user has SSH access to the newserver as 'git@newserver', you
-can pipe the data through SSH.
-
-```
-# As the git user
-tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
- ssh git@newserver tar -C /mnt/gitlab/repositories -xf -
-```
-
-If you want to compress the data before it goes over the network
-(which will cost you CPU cycles) you can replace `ssh` with `ssh -C`.
-
-## The target directory contains an outdated copy of the repositories: use rsync
-
-If the target directory already contains a partial / outdated copy
-of the repositories it may be wasteful to copy all the data again
-with tar. In this scenario it is better to use rsync. This utility
-is either already installed on your system or easily installable
-via apt, yum etc.
-
-```
-# As the 'git' user
-rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
- /mnt/gitlab/repositories
-```
-
-The `/.` in the command above is very important, without it you can
-easily get the wrong directory structure in the target directory.
-If you want to see progress, replace `-a` with `-av`.
-
-### Single rsync to another server
-
-If the 'git' user on your source system has SSH access to the target
-server you can send the repositories over the network with rsync.
-
-```
-# As the 'git' user
-rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
- git@newserver:/mnt/gitlab/repositories
-```
-
-## Thousands of Git repositories: use one rsync per repository
-
-Every time you start an rsync job it has to inspect all files in
-the source directory, all files in the target directory, and then
-decide what files to copy or not. If the source or target directory
-has many contents this startup phase of rsync can become a burden
-for your GitLab server. In cases like this you can make rsync's
-life easier by dividing its work in smaller pieces, and sync one
-repository at a time.
-
-In addition to rsync we will use [GNU
-Parallel](http://www.gnu.org/software/parallel/). This utility is
-not included in GitLab so you need to install it yourself with apt
-or yum. Also note that the GitLab scripts we used below were added
-in GitLab 8.1.
-
-** This process does not clean up repositories at the target location that no
-longer exist at the source. ** If you start using your GitLab instance with
-`/mnt/gitlab/repositories`, you need to run `gitlab-rake gitlab:cleanup:repos`
-after switching to the new repository storage directory.
-
-### Parallel rsync for all repositories known to GitLab
-
-This will sync repositories with 10 rsync processes at a time. We keep
-track of progress so that the transfer can be restarted if necessary.
-
-First we create a new directory, owned by 'git', to hold transfer
-logs. We assume the directory is empty before we start the transfer
-procedure, and that we are the only ones writing files in it.
-
-```
-# Omnibus
-sudo mkdir /var/opt/gitlab/transfer-logs
-sudo chown git:git /var/opt/gitlab/transfer-logs
-
-# Source
-sudo -u git -H mkdir /home/git/transfer-logs
-```
-
-We seed the process with a list of the directories we want to copy.
-
-```
-# Omnibus
-sudo -u git sh -c 'gitlab-rake gitlab:list_repos > /var/opt/gitlab/transfer-logs/all-repos-$(date +%s).txt'
-
-# Source
-cd /home/git/gitlab
-sudo -u git -H sh -c 'bundle exec rake gitlab:list_repos > /home/git/transfer-logs/all-repos-$(date +%s).txt'
-```
-
-Now we can start the transfer. The command below is idempotent, and
-the number of jobs done by GNU Parallel should converge to zero. If it
-does not some repositories listed in all-repos-1234.txt may have been
-deleted/renamed before they could be copied.
-
-```
-# Omnibus
-sudo -u git sh -c '
-cat /var/opt/gitlab/transfer-logs/* | sort | uniq -u |\
- /usr/bin/env JOBS=10 \
- /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \
- /var/opt/gitlab/transfer-logs/success-$(date +%s).log \
- /var/opt/gitlab/git-data/repositories \
- /mnt/gitlab/repositories
-'
-
-# Source
-cd /home/git/gitlab
-sudo -u git -H sh -c '
-cat /home/git/transfer-logs/* | sort | uniq -u |\
- /usr/bin/env JOBS=10 \
- bin/parallel-rsync-repos \
- /home/git/transfer-logs/success-$(date +%s).log \
- /home/git/repositories \
- /mnt/gitlab/repositories
-`
-```
-
-### Parallel rsync only for repositories with recent activity
-
-Suppose you have already done one sync that started after 2015-10-1 12:00 UTC.
-Then you might only want to sync repositories that were changed via GitLab
-_after_ that time. You can use the 'SINCE' variable to tell 'rake
-gitlab:list_repos' to only print repositories with recent activity.
-
-```
-# Omnibus
-sudo gitlab-rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\
- sudo -u git \
- /usr/bin/env JOBS=10 \
- /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \
- success-$(date +%s).log \
- /var/opt/gitlab/git-data/repositories \
- /mnt/gitlab/repositories
-
-# Source
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\
- sudo -u git -H \
- /usr/bin/env JOBS=10 \
- bin/parallel-rsync-repos \
- success-$(date +%s).log \
- /home/git/repositories \
- /mnt/gitlab/repositories
-```
+This document was moved to [administration/operations/moving_repositories](../administration/operations/moving_repositories.md).
diff --git a/doc/operations/sidekiq_memory_killer.md b/doc/operations/sidekiq_memory_killer.md
index b5e78348989..cf7c3b2e2ed 100644
--- a/doc/operations/sidekiq_memory_killer.md
+++ b/doc/operations/sidekiq_memory_killer.md
@@ -1,40 +1 @@
-# Sidekiq MemoryKiller
-
-The GitLab Rails application code suffers from memory leaks. For web requests
-this problem is made manageable using
-[unicorn-worker-killer](https://github.com/kzk/unicorn-worker-killer) which
-restarts Unicorn worker processes in between requests when needed. The Sidekiq
-MemoryKiller applies the same approach to the Sidekiq processes used by GitLab
-to process background jobs.
-
-Unlike unicorn-worker-killer, which is enabled by default for all GitLab
-installations since GitLab 6.4, the Sidekiq MemoryKiller is enabled by default
-_only_ for Omnibus packages. The reason for this is that the MemoryKiller
-relies on Runit to restart Sidekiq after a memory-induced shutdown and GitLab
-installations from source do not all use Runit or an equivalent.
-
-With the default settings, the MemoryKiller will cause a Sidekiq restart no
-more often than once every 15 minutes, with the restart causing about one
-minute of delay for incoming background jobs.
-
-## Configuring the MemoryKiller
-
-The MemoryKiller is controlled using environment variables.
-
-- `SIDEKIQ_MEMORY_KILLER_MAX_RSS`: if this variable is set, and its value is
- greater than 0, then after each Sidekiq job, the MemoryKiller will check the
- RSS of the Sidekiq process that executed the job. If the RSS of the Sidekiq
- process (expressed in kilobytes) exceeds SIDEKIQ_MEMORY_KILLER_MAX_RSS, a
- delayed shutdown is triggered. The default value for Omnibus packages is set
- [in the omnibus-gitlab
- repository](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/attributes/default.rb).
-- `SIDEKIQ_MEMORY_KILLER_GRACE_TIME`: defaults 900 seconds (15 minutes). When
- a shutdown is triggered, the Sidekiq process will keep working normally for
- another 15 minutes.
-- `SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT`: defaults to 30 seconds. When the grace
- time has expired, the MemoryKiller tells Sidekiq to stop accepting new jobs.
- Existing jobs get 30 seconds to finish. After that, the MemoryKiller tells
- Sidekiq to shut down, and an external supervision mechanism (e.g. Runit) must
- restart Sidekiq.
-- `SIDEKIQ_MEMORY_KILLER_SHUTDOWN_SIGNAL`: defaults to `SIGKILL`. The name of
- the final signal sent to the Sidekiq process when we want it to shut down.
+This document was moved to [administration/operations/sidekiq_memory_killer](../administration/operations/sidekiq_memory_killer.md).
diff --git a/doc/operations/unicorn.md b/doc/operations/unicorn.md
index bad61151bda..fbc9697b755 100644
--- a/doc/operations/unicorn.md
+++ b/doc/operations/unicorn.md
@@ -1,86 +1 @@
-# Understanding Unicorn and unicorn-worker-killer
-
-## Unicorn
-
-GitLab uses [Unicorn](http://unicorn.bogomips.org/), a pre-forking Ruby web
-server, to handle web requests (web browsers and Git HTTP clients). Unicorn is
-a daemon written in Ruby and C that can load and run a Ruby on Rails
-application; in our case the Rails application is GitLab Community Edition or
-GitLab Enterprise Edition.
-
-Unicorn has a multi-process architecture to make better use of available CPU
-cores (processes can run on different cores) and to have stronger fault
-tolerance (most failures stay isolated in only one process and cannot take down
-GitLab entirely). On startup, the Unicorn 'master' process loads a clean Ruby
-environment with the GitLab application code, and then spawns 'workers' which
-inherit this clean initial environment. The 'master' never handles any
-requests, that is left to the workers. The operating system network stack
-queues incoming requests and distributes them among the workers.
-
-In a perfect world, the master would spawn its pool of workers once, and then
-the workers handle incoming web requests one after another until the end of
-time. In reality, worker processes can crash or time out: if the master notices
-that a worker takes too long to handle a request it will terminate the worker
-process with SIGKILL ('kill -9'). No matter how the worker process ended, the
-master process will replace it with a new 'clean' process again. Unicorn is
-designed to be able to replace 'crashed' workers without dropping user
-requests.
-
-This is what a Unicorn worker timeout looks like in `unicorn_stderr.log`. The
-master process has PID 56227 below.
-
-```
-[2015-06-05T10:58:08.660325 #56227] ERROR -- : worker=10 PID:53009 timeout (61s > 60s), killing
-[2015-06-05T10:58:08.699360 #56227] ERROR -- : reaped #<Process::Status: pid 53009 SIGKILL (signal 9)> worker=10
-[2015-06-05T10:58:08.708141 #62538] INFO -- : worker=10 spawned pid=62538
-[2015-06-05T10:58:08.708824 #62538] INFO -- : worker=10 ready
-```
-
-### Tunables
-
-The main tunables for Unicorn are the number of worker processes and the
-request timeout after which the Unicorn master terminates a worker process.
-See the [omnibus-gitlab Unicorn settings
-documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/unicorn.md)
-if you want to adjust these settings.
-
-## unicorn-worker-killer
-
-GitLab has memory leaks. These memory leaks manifest themselves in long-running
-processes, such as Unicorn workers. (The Unicorn master process is not known to
-leak memory, probably because it does not handle user requests.)
-
-To make these memory leaks manageable, GitLab comes with the
-[unicorn-worker-killer gem](https://github.com/kzk/unicorn-worker-killer). This
-gem [monkey-patches](https://en.wikipedia.org/wiki/Monkey_patch) the Unicorn
-workers to do a memory self-check after every 16 requests. If the memory of the
-Unicorn worker exceeds a pre-set limit then the worker process exits. The
-Unicorn master then automatically replaces the worker process.
-
-This is a robust way to handle memory leaks: Unicorn is designed to handle
-workers that 'crash' so no user requests will be dropped. The
-unicorn-worker-killer gem is designed to only terminate a worker process _in
-between requests_, so no user requests are affected.
-
-This is what a Unicorn worker memory restart looks like in unicorn_stderr.log.
-You see that worker 4 (PID 125918) is inspecting itself and decides to exit.
-The threshold memory value was 254802235 bytes, about 250MB. With GitLab this
-threshold is a random value between 200 and 250 MB. The master process (PID
-117565) then reaps the worker process and spawns a new 'worker 4' with PID
-127549.
-
-```
-[2015-06-05T12:07:41.828374 #125918] WARN -- : #<Unicorn::HttpServer:0x00000002734770>: worker (pid: 125918) exceeds memory limit (256413696 bytes > 254802235 bytes)
-[2015-06-05T12:07:41.828472 #125918] WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 125918) alive: 23 sec (trial 1)
-[2015-06-05T12:07:42.025916 #117565] INFO -- : reaped #<Process::Status: pid 125918 exit 0> worker=4
-[2015-06-05T12:07:42.034527 #127549] INFO -- : worker=4 spawned pid=127549
-[2015-06-05T12:07:42.035217 #127549] INFO -- : worker=4 ready
-```
-
-One other thing that stands out in the log snippet above, taken from
-GitLab.com, is that 'worker 4' was serving requests for only 23 seconds. This
-is a normal value for our current GitLab.com setup and traffic.
-
-The high frequency of Unicorn memory restarts on some GitLab sites can be a
-source of confusion for administrators. Usually they are a [red
-herring](https://en.wikipedia.org/wiki/Red_herring).
+This document was moved to [administration/operations/unicorn](../administration/operations/unicorn.md).
diff --git a/doc/pages/README.md b/doc/pages/README.md
new file mode 100644
index 00000000000..7878bce3f10
--- /dev/null
+++ b/doc/pages/README.md
@@ -0,0 +1 @@
+This document was moved to [pages/index.md](../user/project/pages/index.md).
diff --git a/doc/pages/administration.md b/doc/pages/administration.md
new file mode 100644
index 00000000000..4eb3bb32c77
--- /dev/null
+++ b/doc/pages/administration.md
@@ -0,0 +1 @@
+This document was moved to [administration/pages](../administration/pages/index.md).
diff --git a/doc/pages/getting_started_part_one.md b/doc/pages/getting_started_part_one.md
new file mode 100644
index 00000000000..1d63ccb4d2f
--- /dev/null
+++ b/doc/pages/getting_started_part_one.md
@@ -0,0 +1 @@
+This document was moved to [another location](../user/project/pages/getting_started_part_one.md).
diff --git a/doc/pages/getting_started_part_three.md b/doc/pages/getting_started_part_three.md
new file mode 100644
index 00000000000..1697b5cd6b4
--- /dev/null
+++ b/doc/pages/getting_started_part_three.md
@@ -0,0 +1 @@
+This document was moved to [another location](../user/project/pages/getting_started_part_three.md).
diff --git a/doc/pages/getting_started_part_two.md b/doc/pages/getting_started_part_two.md
new file mode 100644
index 00000000000..a58affec73d
--- /dev/null
+++ b/doc/pages/getting_started_part_two.md
@@ -0,0 +1 @@
+This document was moved to [another location](../user/project/pages/getting_started_part_two.md).
diff --git a/doc/profile/2fa_u2f_authenticate.png b/doc/profile/2fa_u2f_authenticate.png
deleted file mode 100644
index b9138ff60db..00000000000
--- a/doc/profile/2fa_u2f_authenticate.png
+++ /dev/null
Binary files differ
diff --git a/doc/profile/2fa_u2f_register.png b/doc/profile/2fa_u2f_register.png
deleted file mode 100644
index 15b3683ef73..00000000000
--- a/doc/profile/2fa_u2f_register.png
+++ /dev/null
Binary files differ
diff --git a/doc/profile/README.md b/doc/profile/README.md
index 6f8359d87fa..aed64ac1228 100644
--- a/doc/profile/README.md
+++ b/doc/profile/README.md
@@ -1,4 +1,5 @@
-# Profile Settings
+# Profile settings
-- [Preferences](preferences.md)
-- [Two-factor Authentication (2FA)](two_factor_authentication.md)
+- [Preferences](../user/profile/preferences.md)
+- [Two-factor Authentication (2FA)](../user/profile/account/two_factor_authentication.md)
+- [Deleting your account](../user/profile/account/delete_account.md)
diff --git a/doc/profile/preferences.md b/doc/profile/preferences.md
index 073b8797508..cc16f3afe41 100644
--- a/doc/profile/preferences.md
+++ b/doc/profile/preferences.md
@@ -1,43 +1 @@
-# Profile Preferences
-
-Settings in the **Profile > Preferences** page allow the user to customize
-various aspects of the site to their liking.
-
-## Application theme
-
-Changing this setting allows the user to customize the color scheme used for the
-navigation bar on the left side of the screen.
-
-The default is **Charcoal**.
-
-## Syntax highlighting theme
-
-_GitLab uses the [rouge ruby library][rouge] for syntax highlighting. For a
-list of supported languages visit the rouge website._
-
-Changing this setting allows the user to customize the theme used when viewing
-syntax highlighted code on the site.
-
-The default is **White**.
-
-## Behavior
-
-### Default Dashboard
-
-For users who have access to a large number of projects but only keep up with a
-select few, the amount of activity on the default Dashboard page can be
-overwhelming.
-
-Changing this setting allows the user to redefine what their default dashboard
-will be. Setting it to **Starred Projects** will make that Dashboard view the
-default when signing in or clicking the application logo in the upper left.
-
-The default is **Your Projects**.
-
-### Default Project view
-
-It allows user to choose what content he or she want to see on project page.
-
-The default is **Readme**.
-
-[rouge]: http://rouge.jneen.net/ "Rouge website"
+This document was moved to [another location](../user/profile/preferences.md).
diff --git a/doc/profile/two_factor_authentication.md b/doc/profile/two_factor_authentication.md
index 82505b13401..60918a0339c 100644
--- a/doc/profile/two_factor_authentication.md
+++ b/doc/profile/two_factor_authentication.md
@@ -1,127 +1 @@
-# Two-factor Authentication (2FA)
-
-Two-factor Authentication (2FA) provides an additional level of security to your
-GitLab account. Once enabled, in addition to supplying your username and
-password to login, you'll be prompted for a code generated by an application on
-your phone.
-
-By enabling 2FA, the only way someone other than you can log into your account
-is to know your username and password *and* have access to your phone.
-
-> **Note:**
-When you enable 2FA, don't forget to back up your recovery codes. For your safety, if you
-lose your codes for GitLab.com, we can't disable or recover them.
-
-In addition to a phone application, GitLab supports U2F (universal 2nd factor) devices as
-the second factor of authentication. Once enabled, in addition to supplying your username and
-password to login, you'll be prompted to activate your U2F device (usually by pressing
-a button on it), and it will perform secure authentication on your behalf.
-
-> **Note:** Support for U2F devices was added in version 8.8
-
-The U2F workflow is only supported by Google Chrome at this point, so we _strongly_ recommend
-that you set up both methods of two-factor authentication, so you can still access your account
-from other browsers.
-
-> **Note:** GitLab officially only supports [Yubikey] U2F devices.
-
-## Enabling 2FA
-
-### Enable 2FA via mobile application
-
-**In GitLab:**
-
-1. Log in to your GitLab account.
-1. Go to your **Profile Settings**.
-1. Go to **Account**.
-1. Click **Enable Two-factor Authentication**.
-
-![Two-factor setup](2fa.png)
-
-**On your phone:**
-
-1. Install a compatible application. We recommend [Google Authenticator]
-\(proprietary\) or [FreeOTP] \(open source\).
-1. In the application, add a new entry in one of two ways:
- * Scan the code with your phone's camera to add the entry automatically.
- * Enter the details provided to add the entry manually.
-
-**In GitLab:**
-
-1. Enter the six-digit pin number from the entry on your phone into the **Pin
- code** field.
-1. Click **Submit**.
-
-If the pin you entered was correct, you'll see a message indicating that
-Two-Factor Authentication has been enabled, and you'll be presented with a list
-of recovery codes.
-
-### Enable 2FA via U2F device
-
-**In GitLab:**
-
-1. Log in to your GitLab account.
-1. Go to your **Profile Settings**.
-1. Go to **Account**.
-1. Click **Enable Two-Factor Authentication**.
-1. Plug in your U2F device.
-1. Click on **Setup New U2F Device**.
-1. A light will start blinking on your device. Activate it by pressing its button.
-
-You will see a message indicating that your device was successfully set up.
-Click on **Register U2F Device** to complete the process.
-
-![Two-Factor U2F Setup](2fa_u2f_register.png)
-
-## Recovery Codes
-
-Should you ever lose access to your phone, you can use one of the ten provided
-backup codes to login to your account. We suggest copying or printing them for
-storage in a safe place. **Each code can be used only once** to log in to your
-account.
-
-If you lose the recovery codes or just want to generate new ones, you can do so
-from the **Profile Settings** > **Account** page where you first enabled 2FA.
-
-> **Note:** Recovery codes are not generated for U2F devices.
-
-## Logging in with 2FA Enabled
-
-Logging in with 2FA enabled is only slightly different than a normal login.
-Enter your username and password credentials as you normally would, and you'll
-be presented with a second prompt, depending on which type of 2FA you've enabled.
-
-### Log in via mobile application
-
-Enter the pin from your phone's application or a recovery code to log in.
-
-![Two-Factor Authentication on sign in via OTP](2fa_auth.png)
-
-### Log in via U2F device
-
-1. Click **Login via U2F Device**
-1. A light will start blinking on your device. Activate it by pressing its button.
-
-You will see a message indicating that your device responded to the authentication request.
-Click on **Authenticate via U2F Device** to complete the process.
-
-![Two-Factor Authentication on sign in via U2F device](2fa_u2f_authenticate.png)
-
-## Disabling 2FA
-
-1. Log in to your GitLab account.
-1. Go to your **Profile Settings**.
-1. Go to **Account**.
-1. Click **Disable**, under **Two-Factor Authentication**.
-
-This will clear all your two-factor authentication registrations, including mobile
-applications and U2F devices.
-
-## Note to GitLab administrators
-
-You need to take special care to that 2FA keeps working after
-[restoring a GitLab backup](../raketasks/backup_restore.md).
-
-[Google Authenticator]: https://support.google.com/accounts/answer/1066447?hl=en
-[FreeOTP]: https://fedorahosted.org/freeotp/
-[YubiKey]: https://www.yubico.com/products/yubikey-hardware/
+This document was moved to [user/profile/account](../user/profile/account/two_factor_authentication.md).
diff --git a/doc/project_services/bamboo.md b/doc/project_services/bamboo.md
index 51668128c62..5b171080c72 100644
--- a/doc/project_services/bamboo.md
+++ b/doc/project_services/bamboo.md
@@ -1,60 +1 @@
-# Atlassian Bamboo CI Service
-
-GitLab provides integration with Atlassian Bamboo for continuous integration.
-When configured, pushes to a project will trigger a build in Bamboo automatically.
-Merge requests will also display CI status showing whether the build is pending,
-failed, or completed successfully. It also provides a link to the Bamboo build
-page for more information.
-
-Bamboo doesn't quite provide the same features as a traditional build system when
-it comes to accepting webhooks and commit data. There are a few things that
-need to be configured in a Bamboo build plan before GitLab can integrate.
-
-## Setup
-
-### Complete these steps in Bamboo:
-
-1. Navigate to a Bamboo build plan and choose 'Configure plan' from the 'Actions'
-dropdown.
-1. Select the 'Triggers' tab.
-1. Click 'Add trigger'.
-1. Enter a description such as 'GitLab trigger'
-1. Choose 'Repository triggers the build when changes are committed'
-1. Check one or more repositories checkboxes
-1. Enter the GitLab IP address in the 'Trigger IP addresses' box. This is a
-whitelist of IP addresses that are allowed to trigger Bamboo builds.
-1. Save the trigger.
-1. In the left pane, select a build stage. If you have multiple build stages
-you want to select the last stage that contains the git checkout task.
-1. Select the 'Miscellaneous' tab.
-1. Under 'Pattern Match Labelling' put '${bamboo.repository.revision.number}'
-in the 'Labels' box.
-1. Save
-
-Bamboo is now ready to accept triggers from GitLab. Next, set up the Bamboo
-service in GitLab
-
-### Complete these steps in GitLab:
-
-1. Navigate to the project you want to configure to trigger builds.
-1. Select 'Settings' in the top navigation.
-1. Select 'Services' in the left navigation.
-1. Click 'Atlassian Bamboo CI'
-1. Select the 'Active' checkbox.
-1. Enter the base URL of your Bamboo server. 'https://bamboo.example.com'
-1. Enter the build key from your Bamboo build plan. Build keys are a short,
-all capital letter, identifier that is unique. It will be something like PR-BLD
-1. If necessary, enter username and password for a Bamboo user that has
-access to trigger the build plan. Leave these fields blank if you do not require
-authentication.
-1. Save or optionally click 'Test Settings'. Please note that 'Test Settings'
-will actually trigger a build in Bamboo.
-
-## Troubleshooting
-
-If builds are not triggered, these are a couple of things to keep in mind.
-
-1. Ensure you entered the right GitLab IP address in Bamboo under 'Trigger
-IP addresses'.
-1. Remember that GitLab only triggers builds on push events. A commit via the
-web interface will not trigger CI currently.
+This document was moved to [user/project/integrations/bamboo.md](../user/project/integrations/bamboo.md).
diff --git a/doc/project_services/bugzilla.md b/doc/project_services/bugzilla.md
index 215ed6fe9cc..e67055d5616 100644
--- a/doc/project_services/bugzilla.md
+++ b/doc/project_services/bugzilla.md
@@ -1,17 +1 @@
-# Bugzilla Service
-
-Go to your project's **Settings > Services > Bugzilla** and fill in the required
-details as described in the table below.
-
-| Field | Description |
-| ----- | ----------- |
-| `description` | A name for the issue tracker (to differentiate between instances, for example) |
-| `project_url` | The URL to the project in Bugzilla which is being linked to this GitLab project. Note that the `project_url` requires PRODUCT_NAME to be updated with the product/project name in Bugzilla. |
-| `issues_url` | The URL to the issue in Bugzilla project that is linked to this GitLab project. Note that the `issues_url` requires `:id` in the URL. This ID is used by GitLab as a placeholder to replace the issue number. |
-| `new_issue_url` | This is the URL to create a new issue in Bugzilla for the project linked to this GitLab project. Note that the `new_issue_url` requires PRODUCT_NAME to be updated with the product/project name in Bugzilla. |
-
-Once you have configured and enabled Bugzilla:
-
-- the **Issues** link on the GitLab project pages takes you to the appropriate
- Bugzilla product page
-- clicking **New issue** on the project dashboard takes you to Bugzilla for entering a new issue
+This document was moved to [user/project/integrations/bugzilla.md](../user/project/integrations/bugzilla.md).
diff --git a/doc/project_services/builds_emails.md b/doc/project_services/builds_emails.md
deleted file mode 100644
index af0b1a287c7..00000000000
--- a/doc/project_services/builds_emails.md
+++ /dev/null
@@ -1,16 +0,0 @@
-## Enabling build emails
-
-To receive e-mail notifications about the result status of your builds, visit
-your project's **Settings > Services > Builds emails** and activate the service.
-
-In the _Recipients_ area, provide a list of e-mails separated by comma.
-
-Check the _Add pusher_ checkbox if you want the committer to also receive
-e-mail notifications about each build's status.
-
-If you enable the _Notify only broken builds_ option, e-mail notifications will
-be sent only for failed builds.
-
----
-
-![Builds emails service settings](img/builds_emails_service.png)
diff --git a/doc/project_services/emails_on_push.md b/doc/project_services/emails_on_push.md
index 2f9f36f962e..a2e831ada34 100644
--- a/doc/project_services/emails_on_push.md
+++ b/doc/project_services/emails_on_push.md
@@ -1,17 +1 @@
-## Enabling emails on push
-
-To receive email notifications for every change that is pushed to the project, visit
-your project's **Settings > Services > Emails on push** and activate the service.
-
-In the _Recipients_ area, provide a list of emails separated by commas.
-
-You can configure any of the following settings depending on your preference.
-
-+ **Push events** - Email will be triggered when a push event is recieved
-+ **Tag push events** - Email will be triggered when a tag is created and pushed
-+ **Send from committer** - Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. `user@gitlab.com`).
-+ **Disable code diffs** - Don't include possibly sensitive code diffs in notification body.
-
----
-
-![Email on push service settings](img/emails_on_push_service.png)
+This document was moved to [user/project/integrations/emails_on_push.md](../user/project/integrations/emails_on_push.md).
diff --git a/doc/project_services/hipchat.md b/doc/project_services/hipchat.md
index 021a93a288f..4ae9f6c6b2e 100644
--- a/doc/project_services/hipchat.md
+++ b/doc/project_services/hipchat.md
@@ -1,54 +1 @@
-# Atlassian HipChat
-
-GitLab provides a way to send HipChat notifications upon a number of events,
-such as when a user pushes code, creates a branch or tag, adds a comment, and
-creates a merge request.
-
-## Setup
-
-GitLab requires the use of a HipChat v2 API token to work. v1 tokens are
-not supported at this time. Note the differences between v1 and v2 tokens:
-
-HipChat v1 API (legacy) supports "API Auth Tokens" in the Group API menu. A v1
-token is allowed to send messages to *any* room.
-
-HipChat v2 API has tokens that are can be created using the Integrations tab
-in the Group or Room admin page. By design, these are lightweight tokens that
-allow GitLab to send messages only to *one* room.
-
-### Complete these steps in HipChat:
-
-1. Go to: https://admin.hipchat.com/admin
-1. Click on "Group Admin" -> "Integrations".
-1. Find "Build Your Own!" and click "Create".
-1. Select the desired room, name the integration "GitLab", and click "Create".
-1. In the "Send messages to this room by posting this URL" column, you should
-see a URL in the format:
-
-```
- https://api.hipchat.com/v2/room/<room>/notification?auth_token=<token>
-```
-
-HipChat is now ready to accept messages from GitLab. Next, set up the HipChat
-service in GitLab.
-
-### Complete these steps in GitLab:
-
-1. Navigate to the project you want to configure for notifications.
-1. Select "Settings" in the top navigation.
-1. Select "Services" in the left navigation.
-1. Click "HipChat".
-1. Select the "Active" checkbox.
-1. Insert the `token` field from the URL into the `Token` field on the Web page.
-1. Insert the `room` field from the URL into the `Room` field on the Web page.
-1. Save or optionally click "Test Settings".
-
-## Troubleshooting
-
-If you do not see notifications, make sure you are using a HipChat v2 API
-token, not a v1 token.
-
-Note that the v2 token is tied to a specific room. If you want to be able to
-specify arbitrary rooms, you can create an API token for a specific user in
-HipChat under "Account settings" and "API access". Use the `XXX` value under
-`auth_token=XXX`.
+This document was moved to [user/project/integrations/hipchat.md](../user/project/integrations/hipchat.md).
diff --git a/doc/project_services/img/builds_emails_service.png b/doc/project_services/img/builds_emails_service.png
deleted file mode 100644
index 88943dc410e..00000000000
--- a/doc/project_services/img/builds_emails_service.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/emails_on_push_service.png b/doc/project_services/img/emails_on_push_service.png
deleted file mode 100644
index cd6f79ad1eb..00000000000
--- a/doc/project_services/img/emails_on_push_service.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_add_gitlab_commit_message.png b/doc/project_services/img/jira_add_gitlab_commit_message.png
deleted file mode 100644
index aec472b9118..00000000000
--- a/doc/project_services/img/jira_add_gitlab_commit_message.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_add_user_to_group.png b/doc/project_services/img/jira_add_user_to_group.png
deleted file mode 100644
index 0ba737bda9a..00000000000
--- a/doc/project_services/img/jira_add_user_to_group.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_create_new_group.png b/doc/project_services/img/jira_create_new_group.png
deleted file mode 100644
index 0609060cb05..00000000000
--- a/doc/project_services/img/jira_create_new_group.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_create_new_group_name.png b/doc/project_services/img/jira_create_new_group_name.png
deleted file mode 100644
index 53d77b17df0..00000000000
--- a/doc/project_services/img/jira_create_new_group_name.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_create_new_user.png b/doc/project_services/img/jira_create_new_user.png
deleted file mode 100644
index 9eaa444ed25..00000000000
--- a/doc/project_services/img/jira_create_new_user.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_group_access.png b/doc/project_services/img/jira_group_access.png
deleted file mode 100644
index 8d4657427ae..00000000000
--- a/doc/project_services/img/jira_group_access.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_issue_closed.png b/doc/project_services/img/jira_issue_closed.png
deleted file mode 100644
index acdd83702d3..00000000000
--- a/doc/project_services/img/jira_issue_closed.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_issue_reference.png b/doc/project_services/img/jira_issue_reference.png
deleted file mode 100644
index 1a2d9f04a6c..00000000000
--- a/doc/project_services/img/jira_issue_reference.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_issues_workflow.png b/doc/project_services/img/jira_issues_workflow.png
deleted file mode 100644
index 0703081d77b..00000000000
--- a/doc/project_services/img/jira_issues_workflow.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_merge_request_close.png b/doc/project_services/img/jira_merge_request_close.png
deleted file mode 100644
index 47785e3ba27..00000000000
--- a/doc/project_services/img/jira_merge_request_close.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_project_name.png b/doc/project_services/img/jira_project_name.png
deleted file mode 100644
index e785ec6140d..00000000000
--- a/doc/project_services/img/jira_project_name.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_reference_commit_message_in_jira_issue.png b/doc/project_services/img/jira_reference_commit_message_in_jira_issue.png
deleted file mode 100644
index fb270d85e3c..00000000000
--- a/doc/project_services/img/jira_reference_commit_message_in_jira_issue.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_service.png b/doc/project_services/img/jira_service.png
deleted file mode 100644
index 13aefce6f84..00000000000
--- a/doc/project_services/img/jira_service.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_service_close_issue.png b/doc/project_services/img/jira_service_close_issue.png
deleted file mode 100644
index eed69e80d2c..00000000000
--- a/doc/project_services/img/jira_service_close_issue.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_service_page.png b/doc/project_services/img/jira_service_page.png
deleted file mode 100644
index a5b49c501ba..00000000000
--- a/doc/project_services/img/jira_service_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_submit_gitlab_merge_request.png b/doc/project_services/img/jira_submit_gitlab_merge_request.png
deleted file mode 100644
index 77630d39d39..00000000000
--- a/doc/project_services/img/jira_submit_gitlab_merge_request.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_user_management_link.png b/doc/project_services/img/jira_user_management_link.png
deleted file mode 100644
index 5f002b59bac..00000000000
--- a/doc/project_services/img/jira_user_management_link.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/jira_workflow_screenshot.png b/doc/project_services/img/jira_workflow_screenshot.png
deleted file mode 100644
index 937a50a77d9..00000000000
--- a/doc/project_services/img/jira_workflow_screenshot.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/redmine_configuration.png b/doc/project_services/img/redmine_configuration.png
deleted file mode 100644
index e9d8c0d2da8..00000000000
--- a/doc/project_services/img/redmine_configuration.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/services_templates_redmine_example.png b/doc/project_services/img/services_templates_redmine_example.png
deleted file mode 100644
index 77c2b98e5d0..00000000000
--- a/doc/project_services/img/services_templates_redmine_example.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/img/slack_configuration.png b/doc/project_services/img/slack_configuration.png
deleted file mode 100644
index b8de8a56db7..00000000000
--- a/doc/project_services/img/slack_configuration.png
+++ /dev/null
Binary files differ
diff --git a/doc/project_services/irker.md b/doc/project_services/irker.md
index 25c0c3ad2a6..7f0850dcc24 100644
--- a/doc/project_services/irker.md
+++ b/doc/project_services/irker.md
@@ -1,51 +1 @@
-# Irker IRC Gateway
-
-GitLab provides a way to push update messages to an Irker server. When
-configured, pushes to a project will trigger the service to send data directly
-to the Irker server.
-
-See the project homepage for further info: https://gitlab.com/esr/irker
-
-## Needed setup
-
-You will first need an Irker daemon. You can download the Irker code from its
-repository on https://gitlab.com/esr/irker:
-
-```
-git clone https://gitlab.com/esr/irker.git
-```
-
-Once you have downloaded the code, you can run the python script named `irkerd`.
-This script is the gateway script, it acts both as an IRC client, for sending
-messages to an IRC server obviously, and as a TCP server, for receiving messages
-from the GitLab service.
-
-If the Irker server runs on the same machine, you are done. If not, you will
-need to follow the firsts steps of the next section.
-
-## Complete these steps in GitLab:
-
-1. Navigate to the project you want to configure for notifications.
-1. Select "Settings" in the top navigation.
-1. Select "Services" in the left navigation.
-1. Click "Irker".
-1. Select the "Active" checkbox.
-1. Enter the server host address where `irkerd` runs (defaults to `localhost`)
-in the `Server host` field on the Web page
-1. Enter the server port of `irkerd` (e.g. defaults to 6659) in the
-`Server port` field on the Web page.
-1. Optional: if `Default IRC URI` is set, it has to be in the format
-`irc[s]://domain.name` and will be prepend to each and every channel provided
-by the user which is not a full URI.
-1. Specify the recipients (e.g. #channel1, user1, etc.)
-1. Save or optionally click "Test Settings".
-
-## Note on Irker recipients
-
-Irker accepts channel names of the form `chan` and `#chan`, both for the
-`#chan` channel. If you want to send messages in query, you will need to add
-`,isnick` after the channel name, in this form: `Aorimn,isnick`. In this latter
-case, `Aorimn` is treated as a nick and no more as a channel name.
-
-Irker can also join password-protected channels. Users need to append
-`?key=thesecretpassword` to the chan name.
+This document was moved to [user/project/integrations/irker.md](../user/project/integrations/irker.md).
diff --git a/doc/project_services/jira.md b/doc/project_services/jira.md
index b626c746c79..63614feba82 100644
--- a/doc/project_services/jira.md
+++ b/doc/project_services/jira.md
@@ -1,246 +1 @@
-# GitLab JIRA integration
-
->**Note:**
-Full JIRA integration was previously exclusive to GitLab Enterprise Edition.
-With [GitLab 8.3 forward][8_3_post], this feature in now [backported][jira-ce]
-to GitLab Community Edition as well.
-
----
-
-GitLab can be configured to interact with [JIRA Core] either using an
-on-premises instance or the SaaS solution that Atlassian offers. Configuration
-happens via username and password on a per-project basis. Connecting to a JIRA
-server via CAS is not possible.
-
-Each project can be configured to connect to a different JIRA instance or, in
-case you have a single JIRA instance, you can pre-fill the JIRA service
-settings page in GitLab with a default template. To configure the JIRA template,
-see the [Services Templates documentation][services-templates].
-
-Once the GitLab project is connected to JIRA, you can reference and close the
-issues in JIRA directly from GitLab's merge requests.
-
-## Configuration
-
-The configuration consists of two parts:
-
-- [JIRA configuration](#configuring-jira)
-- [GitLab configuration](#configuring-gitlab)
-
-### Configuring JIRA
-
-First things first, we need to create a user in JIRA which will have access to
-all projects that need to integrate with GitLab.
-
-We have split this stage in steps so it is easier to follow.
-
----
-
-1. Login to your JIRA instance as an administrator and under **Administration**
- go to **User Management** to create a new user.
-
- ![JIRA user management link](img/jira_user_management_link.png)
-
- ---
-
-1. The next step is to create a new user (e.g., `gitlab`) who has write access
- to projects in JIRA. Enter the user's name and a _valid_ e-mail address
- since JIRA sends a verification e-mail to set-up the password.
- _**Note:** JIRA creates the username automatically by using the e-mail
- prefix. You can change it later if you want._
-
- ![JIRA create new user](img/jira_create_new_user.png)
-
- ---
-
-1. Now, let's create a `gitlab-developers` group which will have write access
- to projects in JIRA. Go to the **Groups** tab and select **Create group**.
-
- ![JIRA create new user](img/jira_create_new_group.png)
-
- ---
-
- Give it an optional description and hit **Create group**.
-
- ![JIRA create new group](img/jira_create_new_group_name.png)
-
- ---
-
-1. Give the newly-created group write access by going to
- **Application access > View configuration** and adding the `gitlab-developers`
- group to JIRA Core.
-
- ![JIRA group access](img/jira_group_access.png)
-
- ---
-
-1. Add the `gitlab` user to the `gitlab-developers` group by going to
- **Users > GitLab user > Add group** and selecting the `gitlab-developers`
- group from the dropdown menu. Notice that the group says _Access_ which is
- what we aim for.
-
- ![JIRA add user to group](img/jira_add_user_to_group.png)
-
----
-
-The JIRA configuration is over. Write down the new JIRA username and its
-password as they will be needed when configuring GitLab in the next section.
-
-### Configuring GitLab
-
->**Note:**
-The currently supported JIRA versions are v6.x and v7.x. and GitLab
-7.8 or higher is required.
-
----
-
-Assuming you [have already configured JIRA](#configuring-jira), now it's time
-to configure GitLab.
-
-JIRA configuration in GitLab is done via a project's
-[**Services**](../project_services/project_services.md).
-
-To enable JIRA integration in a project, navigate to the project's
-**Settings > Services > JIRA**.
-
-Fill in the required details on the page, as described in the table below.
-
-| Setting | Description |
-| ------- | ----------- |
-| `Description` | A name for the issue tracker (to differentiate between instances, for example). |
-| `Project url` | The URL to the JIRA project which is being linked to this GitLab project. It is of the form: `https://<jira_host_url>/issues/?jql=project=<jira_project>`. |
-| `Issues url` | The URL to the JIRA project issues overview for the project that is linked to this GitLab project. It is of the form: `https://<jira_host_url>/browse/:id`. Leave `:id` as-is, it gets replaced by GitLab at runtime. |
-| `New issue url` | This is the URL to create a new issue in JIRA for the project linked to this GitLab project, and it is of the form: `https://<jira_host_url>/secure/CreateIssue.jspa` |
-| `Api url` | The base URL of the JIRA API. It may be omitted, in which case GitLab will automatically use API version `2` based on the `project url`. It is of the form: `https://<jira_host_url>/rest/api/2`. |
-| `Username` | The username of the user created in [configuring JIRA step](#configuring-jira). |
-| `Password` |The password of the user created in [configuring JIRA step](#configuring-jira). |
-| `JIRA issue transition` | This setting is very important to set up correctly. It is the ID of a transition that moves issues to a closed state. You can find this number under the JIRA workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column ([see screenshot][trans]). By default, this ID is set to `2`. |
-
-After saving the configuration, your GitLab project will be able to interact
-with the linked JIRA project.
-
-For example, given the settings below:
-
-- the JIRA URL is `https://jira.example.com`
-- the project is named `GITLAB`
-- the user is named `gitlab`
-- the JIRA issue transition is 151 (based on the [JIRA issue transition][trans])
-
-the following screenshot shows how the JIRA service settings should look like.
-
-![JIRA service page](img/jira_service_page.png)
-
-[trans]: img/jira_issues_workflow.png
-
----
-
-## JIRA issues
-
-By now you should have [configured JIRA](#configuring-jira) and enabled the
-[JIRA service in GitLab](#configuring-gitlab). If everything is set up correctly
-you should be able to reference and close JIRA issues by just mentioning their
-ID in GitLab commits and merge requests.
-
-### Referencing JIRA Issues
-
-If you reference a JIRA issue, e.g., `GITLAB-1`, in a commit comment, a link
-which points back to JIRA is created.
-
-The same works for comments in merge requests as well.
-
-![JIRA add GitLab commit message](img/jira_add_gitlab_commit_message.png)
-
----
-
-The mentioning action is two-fold, so a comment with a JIRA issue in GitLab
-will automatically add a comment in that particular JIRA issue with the link
-back to GitLab.
-
-
-![JIRA reference commit message](img/jira_reference_commit_message_in_jira_issue.png)
-
----
-
-The comment on the JIRA issue is of the form:
-
-> USER mentioned this issue in LINK_TO_THE_MENTION
-
-Where:
-
-| Format | Description |
-| ------ | ----------- |
-| `USER` | A user that mentioned the issue. This is the link to the user profile in GitLab. |
-| `LINK_TO_THE_MENTION` | Link to the origin of mention with a name of the entity where JIRA issue was mentioned. Can be commit or merge request. |
-
-### Closing JIRA issues
-
-JIRA issues can be closed directly from GitLab by using trigger words in
-commits and merge requests. When a commit which contains the trigger word
-followed by the JIRA issue ID in the commit message is pushed, GitLab will
-add a comment in the mentioned JIRA issue and immediately close it (provided
-the transition ID was set up correctly).
-
-There are currently three trigger words, and you can use either one to achieve
-the same goal:
-
-- `Resolves GITLAB-1`
-- `Closes GITLAB-1`
-- `Fixes GITLAB-1`
-
-where `GITLAB-1` the issue ID of the JIRA project.
-
-### JIRA issue closing example
-
-Let's say for example that we submitted a bug fix and created a merge request
-in GitLab. The workflow would be something like this:
-
-1. Create a new branch
-1. Fix the bug
-1. Commit the changes and push branch to GitLab
-1. Open a new merge request and reference the JIRA issue including one of the
- trigger words, e.g.: `Fixes GITLAB-1`, in the description
-1. Submit the merge request
-1. Ask someone to review
-1. Merge the merge request
-1. The JIRA issue is automatically closed
-
----
-
-In the following screenshot you can see what the link references to the JIRA
-issue look like.
-
-![JIRA - submit a GitLab merge request](img/jira_submit_gitlab_merge_request.png)
-
----
-
-Once this merge request is merged, the JIRA issue will be automatically closed
-with a link to the commit that resolved the issue.
-
-![The GitLab integration user leaves a comment on JIRA](img/jira_issue_closed.png)
-
----
-
-You can see from the above image that there are four references to GitLab:
-
-- The first is from a comment in a specific commit
-- The second is from the JIRA issue reference in the merge request description
-- The third is from the actual commit that solved the issue
-- And the fourth is from the commit that the merge request created
-
-[services-templates]: ../project_services/services_templates.md "Services templates documentation"
-[JIRA Core]: https://www.atlassian.com/software/jira/core "The JIRA Core website"
-[jira-ce]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2146 "MR - Backport JIRA service"
-[8_3_post]: https://about.gitlab.com/2015/12/22/gitlab-8-3-released/ "GitLab 8.3 release post"
-
-## Troubleshooting
-
-### GitLab is unable to comment on a ticket
-
-Make sure that the user you set up for GitLab to communicate with JIRA has the
-correct access permission to post comments on a ticket and to also transition the
-ticket, if you'd like GitLab to also take care of closing them.
-
-### GitLab is unable to close a ticket
-
-Make sure the the `Transition ID` you set within the JIRA settings matches the
-one your project needs to close a ticket.
+This document was moved to [user/project/integrations/jira.md](../user/project/integrations/jira.md).
diff --git a/doc/project_services/kubernetes.md b/doc/project_services/kubernetes.md
new file mode 100644
index 00000000000..0497a13c2b7
--- /dev/null
+++ b/doc/project_services/kubernetes.md
@@ -0,0 +1 @@
+This document was moved to [user/project/integrations/kubernetes.md](../user/project/integrations/kubernetes.md).
diff --git a/doc/project_services/mattermost.md b/doc/project_services/mattermost.md
new file mode 100644
index 00000000000..554a028853e
--- /dev/null
+++ b/doc/project_services/mattermost.md
@@ -0,0 +1 @@
+This document was moved to [user/project/integrations/mattermost.md](../user/project/integrations/mattermost.md).
diff --git a/doc/project_services/mattermost_slash_commands.md b/doc/project_services/mattermost_slash_commands.md
new file mode 100644
index 00000000000..7c238b5dc37
--- /dev/null
+++ b/doc/project_services/mattermost_slash_commands.md
@@ -0,0 +1 @@
+This document was moved to [user/project/integrations/mattermost_slash_commands.md](../user/project/integrations/mattermost_slash_commands.md).
diff --git a/doc/project_services/project_services.md b/doc/project_services/project_services.md
index 4442b7c1742..2c555c4edae 100644
--- a/doc/project_services/project_services.md
+++ b/doc/project_services/project_services.md
@@ -1,55 +1 @@
-# Project Services
-
-Project services allow you to integrate GitLab with other applications. Below
-is list of the currently supported ones.
-
-You can find these within GitLab in the Services page under Project Settings if
-you are at least a master on the project.
-Project Services are a bit like plugins in that they allow a lot of freedom in
-adding functionality to GitLab. For example there is also a service that can
-send an email every time someone pushes new commits.
-
-Because GitLab is open source we can ship with the code and tests for all
-plugins. This allows the community to keep the plugins up to date so that they
-always work in newer GitLab versions.
-
-For an overview of what projects services are available without logging in,
-please see the [project_services directory][projects-code].
-
-[projects-code]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/models/project_services
-
-Click on the service links to see
-further configuration instructions and details. Contributions are welcome.
-
-## Services
-
-| Service | Description |
-| ------- | ----------- |
-| Asana | Asana - Teamwork without email |
-| Assembla | Project Management Software (Source Commits Endpoint) |
-| [Atlassian Bamboo CI](bamboo.md) | A continuous integration and build server |
-| Buildkite | Continuous integration and deployments |
-| [Builds emails](builds_emails.md) | Email the builds status to a list of recipients |
-| [Bugzilla](bugzilla.md) | Bugzilla issue tracker |
-| Campfire | Simple web-based real-time group chat |
-| Custom Issue Tracker | Custom issue tracker |
-| Drone CI | Continuous Integration platform built on Docker, written in Go |
-| [Emails on push](emails_on_push.md) | Email the commits and diff of each push to a list of recipients |
-| External Wiki | Replaces the link to the internal wiki with a link to an external wiki |
-| Flowdock | Flowdock is a collaboration web app for technical teams |
-| Gemnasium | Gemnasium monitors your project dependencies and alerts you about updates and security vulnerabilities |
-| [HipChat](hipchat.md) | Private group chat and IM |
-| [Irker (IRC gateway)](irker.md) | Send IRC messages, on update, to a list of recipients through an Irker gateway |
-| [JIRA](jira.md) | JIRA issue tracker |
-| JetBrains TeamCity CI | A continuous integration and build server |
-| PivotalTracker | Project Management Software (Source Commits Endpoint) |
-| Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop |
-| [Redmine](redmine.md) | Redmine issue tracker |
-| [Slack](slack.md) | A team communication tool for the 21st century |
-
-## Services Templates
-
-Services templates is a way to set some predefined values in the Service of
-your liking which will then be pre-filled on each project's Service.
-
-Read more about [Services Templates in this document](services_templates.md).
+This document was moved to [user/project/integrations/project_services.md](../user/project/integrations/project_services.md).
diff --git a/doc/project_services/redmine.md b/doc/project_services/redmine.md
index b9830ea7c38..6010aa4dc75 100644
--- a/doc/project_services/redmine.md
+++ b/doc/project_services/redmine.md
@@ -1,21 +1 @@
-# Redmine Service
-
-Go to your project's **Settings > Services > Redmine** and fill in the required
-details as described in the table below.
-
-| Field | Description |
-| ----- | ----------- |
-| `description` | A name for the issue tracker (to differentiate between instances, for example) |
-| `project_url` | The URL to the project in Redmine which is being linked to this GitLab project |
-| `issues_url` | The URL to the issue in Redmine project that is linked to this GitLab project. Note that the `issues_url` requires `:id` in the URL. This ID is used by GitLab as a placeholder to replace the issue number. |
-| `new_issue_url` | This is the URL to create a new issue in Redmine for the project linked to this GitLab project |
-
-Once you have configured and enabled Redmine:
-
-- the **Issues** link on the GitLab project pages takes you to the appropriate
- Redmine issue index
-- clicking **New issue** on the project dashboard creates a new Redmine issue
-
-As an example, below is a configuration for a project named gitlab-ci.
-
-![Redmine configuration](img/redmine_configuration.png)
+This document was moved to [user/project/integrations/redmine.md](../user/project/integrations/redmine.md).
diff --git a/doc/project_services/services_templates.md b/doc/project_services/services_templates.md
index be6d13b6d2b..8905d667c5a 100644
--- a/doc/project_services/services_templates.md
+++ b/doc/project_services/services_templates.md
@@ -1,25 +1 @@
-# Services Templates
-
-A GitLab administrator can add a service template that sets a default for each
-project. This makes it much easier to configure individual projects.
-
-After the template is created, the template details will be pre-filled on a
-project's Service page.
-
-## Enable a Service template
-
-In GitLab's Admin area, navigate to **Service Templates** and choose the
-service template you wish to create.
-
-For example, in the image below you can see Redmine.
-
-![Redmine service template](img/services_templates_redmine_example.png)
-
----
-
-**NOTE:** For each project, you will still need to configure the issue tracking
-URLs by replacing `:issues_tracker_id` in the above screenshot with the ID used
-by your external issue tracker. Prior to GitLab v7.8, this ID was configured in
-the project settings, and GitLab would automatically update the URL configured
-in `gitlab.yml`. This behavior is now deprecated and all issue tracker URLs
-must be configured directly within the project's **Services** settings.
+This document was moved to [user/project/integrations/services_templates.md](../user/project/integrations/services_templates.md).
diff --git a/doc/project_services/slack.md b/doc/project_services/slack.md
index 3cfe77c9f85..1d3f98705e3 100644
--- a/doc/project_services/slack.md
+++ b/doc/project_services/slack.md
@@ -1,50 +1 @@
-# Slack Service
-
-## On Slack
-
-To enable Slack integration you must create an incoming webhook integration on
-Slack:
-
-1. [Sign in to Slack](https://slack.com/signin)
-1. Visit [Incoming WebHooks](https://my.slack.com/services/new/incoming-webhook/)
-1. Choose the channel name you want to send notifications to.
-1. Click **Add Incoming WebHooks Integration**
-1. Copy the **Webhook URL**, we'll need this later for GitLab.
-
-## On GitLab
-
-After you set up Slack, it's time to set up GitLab.
-
-Go to your project's **Settings > Services > Slack** and you will see a
-checkbox with the following events that can be triggered:
-
-- Push
-- Issue
-- Merge request
-- Note
-- Tag push
-- Build
-- Wiki page
-
-Bellow each of these event checkboxes, you will have an input field to insert
-which Slack channel you want to send that event message, with `#general`
-being the default. Enter your preferred channel **without** the hash sign (`#`).
-
-At the end, fill in your Slack details:
-
-| Field | Description |
-| ----- | ----------- |
-| **Webhook** | The [incoming webhook URL][slackhook] which you have to setup on Slack. |
-| **Username** | Optional username which can be on messages sent to slack. Fill this in if you want to change the username of the bot. |
-| **Notify only broken builds** | If you choose to enable the **Build** event and you want to be only notified about failed builds. |
-
-After you are all done, click **Save changes** for the changes to take effect.
-
->**Note:**
-You can set "branch,pushed,Compare changes" as highlight words on your Slack
-profile settings, so that you can be aware of new commits when somebody pushes
-them.
-
-![Slack configuration](img/slack_configuration.png)
-
-[slackhook]: https://my.slack.com/services/new/incoming-webhook
+This document was moved to [user/project/integrations/slack.md](../user/project/integrations/slack.md).
diff --git a/doc/project_services/slack_slash_commands.md b/doc/project_services/slack_slash_commands.md
new file mode 100644
index 00000000000..9554c8decc8
--- /dev/null
+++ b/doc/project_services/slack_slash_commands.md
@@ -0,0 +1 @@
+This document was moved to [user/project/integrations/slack_slash_commands.md](../user/project/integrations/slack_slash_commands.md).
diff --git a/doc/public_access/img/restrict_visibility_levels.png b/doc/public_access/img/restrict_visibility_levels.png
new file mode 100644
index 00000000000..c7d4d87981f
--- /dev/null
+++ b/doc/public_access/img/restrict_visibility_levels.png
Binary files differ
diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md
index a3921f1b89f..e8f4c73120c 100644
--- a/doc/public_access/public_access.md
+++ b/doc/public_access/public_access.md
@@ -52,7 +52,7 @@ for anonymous users. The group page now has a visibility level icon.
## Visibility of users
-The public page of a user, located at `/u/username`, is always visible whether
+The public page of a user, located at `/username`, is always visible whether
you are logged in or not.
When visiting the public page of a user, you can only see the projects which
@@ -60,10 +60,13 @@ you are privileged to.
If the public level is restricted, user profiles are only visible to logged in users.
-
## Restricting the use of public or internal projects
In the Admin area under **Settings** (`/admin/application_settings`), you can
restrict the use of visibility levels for users when they create a project or a
-snippet. This is useful to prevent people exposing their repositories to public
+snippet:
+
+![Restrict visibility levels](img/restrict_visibility_levels.png)
+
+This is useful to prevent people exposing their repositories to public
by accident. The restricted visibility settings do not apply to admin users.
diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md
index a49c43b8ef2..2b81ebc9c59 100644
--- a/doc/raketasks/README.md
+++ b/doc/raketasks/README.md
@@ -4,7 +4,8 @@
- [Check](check.md)
- [Cleanup](cleanup.md)
- [Features](features.md)
-- [Maintenance](maintenance.md) and self-checks
+- [LDAP Maintenance](../administration/raketasks/ldap.md)
+- [General Maintenance](maintenance.md) and self-checks
- [User management](user_management.md)
- [Webhooks](web_hooks.md)
- [Import](import.md) of git repositories in bulk
diff --git a/doc/raketasks/backup_hrz.png b/doc/raketasks/backup_hrz.png
index 42084717ebe..c9595b236ee 100644
--- a/doc/raketasks/backup_hrz.png
+++ b/doc/raketasks/backup_hrz.png
Binary files differ
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index 3f4056dc440..855f437cd73 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -1,38 +1,54 @@
-# Backup restore
+# Backing up and restoring GitLab
![backup banner](backup_hrz.png)
-## Create a backup of the GitLab system
+An application data backup creates an archive file that contains the database,
+all repositories and all attachments.
-A backup creates an archive file that contains the database, all repositories and all attachments.
-This archive will be saved in backup_path (see `config/gitlab.yml`).
-The filename will be `[TIMESTAMP]_gitlab_backup.tar`. This timestamp can be used to restore an specific backup.
-You can only restore a backup to exactly the same version of GitLab that you created it
-on, for example 7.2.1. The best way to migrate your repositories from one server to
+You can only restore a backup to **exactly the same version** of GitLab on which
+it was created. The best way to migrate your repositories from one server to
another is through backup restore.
-You need to keep separate copies of `/etc/gitlab/gitlab-secrets.json` and
-`/etc/gitlab/gitlab.rb` (for omnibus packages) or
-`/home/git/gitlab/config/secrets.yml` (for installations from source). This file
-contains the database encryption keys used for two-factor authentication and CI
-secret variables, among other things. If you restore a GitLab backup without
-restoring the database encryption key, users who have two-factor authentication
-enabled will lose access to your GitLab server.
+## Backup
+
+GitLab provides a simple command line interface to backup your whole installation,
+and is flexible enough to fit your needs.
+
+### Backup timestamp
+
+>**Note:**
+In GitLab 9.2 the timestamp format was changed from `EPOCH_YYYY_MM_DD` to
+`EPOCH_YYYY_MM_DD_GitLab version`, for example `1493107454_2017_04_25`
+would become `1493107454_2017_04_25_9.1.0`.
+
+The backup archive will be saved in `backup_path`, which is specified in the
+`config/gitlab.yml` file.
+The filename will be `[TIMESTAMP]_gitlab_backup.tar`, where `TIMESTAMP`
+identifies the time at which each backup was created, plus the GitLab version.
+The timestamp is needed if you need to restore GitLab and multiple backups are
+available.
+
+For example, if the backup name is `1493107454_2017_04_25_9.1.0_gitlab_backup.tar`,
+then the timestamp is `1493107454_2017_04_25_9.1.0`.
+
+### Creating a backup of the GitLab system
+
+Use this command if you've installed GitLab with the Omnibus package:
```
-# use this command if you've installed GitLab with the Omnibus package
sudo gitlab-rake gitlab:backup:create
+```
-# if you've installed GitLab from source
+Use this if you've installed GitLab from source:
+
+```
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
-Also you can choose what should be backed up by adding environment variable SKIP. Available options: db,
-uploads (attachments), repositories, builds(CI build output logs), artifacts (CI build artifacts), lfs (LFS objects).
-Use a comma to specify several options at the same time.
+If you are running GitLab within a Docker container, you can run the backup from the host:
```
-sudo gitlab-rake gitlab:backup:create SKIP=db,uploads
+docker exec -t <container name> gitlab-rake gitlab:backup:create
```
Example output:
@@ -64,14 +80,63 @@ Deleting tmp directories...[DONE]
Deleting old backups... [SKIPPING]
```
-## Upload backups to remote (cloud) storage
+### Backup strategy option
+
+> **Note:** Introduced as an option in GitLab 8.17.
+
+The default backup strategy is to essentially stream data from the respective
+data locations to the backup using the Linux command `tar` and `gzip`. This works
+fine in most cases, but can cause problems when data is rapidly changing.
+
+When data changes while `tar` is reading it, the error `file changed as we read
+it` may occur, and will cause the backup process to fail. To combat this, 8.17
+introduces a new backup strategy called `copy`. The strategy copies data files
+to a temporary location before calling `tar` and `gzip`, avoiding the error.
+
+A side-effect is that the backup process with take up to an additional 1X disk
+space. The process does its best to clean up the temporary files at each stage
+so the problem doesn't compound, but it could be a considerable change for large
+installations. This is why the `copy` strategy is not the default in 8.17.
+
+To use the `copy` strategy instead of the default streaming strategy, specify
+`STRATEGY=copy` in the Rake task command. For example,
+`sudo gitlab-rake gitlab:backup:create STRATEGY=copy`.
+
+### Excluding specific directories from the backup
+
+You can choose what should be backed up by adding the environment variable `SKIP`.
+The available options are:
+
+- `db` (database)
+- `uploads` (attachments)
+- `repositories` (Git repositories data)
+- `builds` (CI job output logs)
+- `artifacts` (CI job artifacts)
+- `lfs` (LFS objects)
+- `registry` (Container Registry images)
+- `pages` (Pages content)
+
+Use a comma to specify several options at the same time:
+
+```
+# use this command if you've installed GitLab with the Omnibus package
+sudo gitlab-rake gitlab:backup:create SKIP=db,uploads
+
+# if you've installed GitLab from source
+sudo -u git -H bundle exec rake gitlab:backup:create SKIP=db,uploads RAILS_ENV=production
+```
+
+### Uploading backups to a remote (cloud) storage
Starting with GitLab 7.4 you can let the backup script upload the '.tar' file it creates.
It uses the [Fog library](http://fog.io/) to perform the upload.
-In the example below we use Amazon S3 for storage.
-But Fog also lets you use [other storage providers](http://fog.io/storage/).
+In the example below we use Amazon S3 for storage, but Fog also lets you use
+[other storage providers](http://fog.io/storage/). GitLab
+[imports cloud drivers](https://gitlab.com/gitlab-org/gitlab-ce/blob/30f5b9a5b711b46f1065baf755e413ceced5646b/Gemfile#L88)
+for AWS, Google, OpenStack Swift, Rackspace and Aliyun as well. A local driver is
+[also available](#uploading-to-locally-mounted-shares).
-For omnibus packages:
+For omnibus packages, add the following to `/etc/gitlab/gitlab.rb`:
```ruby
gitlab_rails['backup_upload_connection'] = {
@@ -86,6 +151,8 @@ gitlab_rails['backup_upload_connection'] = {
gitlab_rails['backup_upload_remote_directory'] = 'my.s3.bucket'
```
+Make sure to run `sudo gitlab-ctl reconfigure` after editing `/etc/gitlab/gitlab.rb` to reflect the changes.
+
For installations from source:
```yaml
@@ -105,6 +172,8 @@ For installations from source:
remote_directory: 'my.s3.bucket'
# Turns on AWS Server-Side Encryption with Amazon S3-Managed Keys for backups, this is optional
# encryption: 'AES256'
+ # Specifies Amazon S3 storage class to use for backups, this is optional
+ # storage_class: 'STANDARD'
```
If you are uploading your backups to S3 you will probably want to create a new
@@ -161,7 +230,7 @@ with the name of your bucket:
### Uploading to locally mounted shares
You may also send backups to a mounted share (`NFS` / `CIFS` / `SMB` / etc.) by
-using the [`Local`](https://github.com/fog/fog-local#usage) storage provider.
+using the Fog [`Local`](https://github.com/fog/fog-local#usage) storage provider.
The directory pointed to by the `local_root` key **must** be owned by the `git`
user **when mounted** (mounting with the `uid=` of the `git` user for `CIFS` and
`SMB`) or the user that you are executing the backup tasks under (for omnibus
@@ -201,9 +270,10 @@ For installations from source:
remote_directory: 'gitlab_backups'
```
-## Backup archive permissions
+### Backup archive permissions
-The backup archives created by GitLab (123456_gitlab_backup.tar) will have owner/group git:git and 0600 permissions by default.
+The backup archives created by GitLab (`1393513186_2014_02_27_gitlab_backup.tar`)
+will have owner/group git:git and 0600 permissions by default.
This is meant to avoid other system users reading GitLab's data.
If you need the backup archives to have different permissions you can use the 'archive_permissions' setting.
@@ -218,28 +288,91 @@ gitlab_rails['backup_archive_permissions'] = 0644 # Makes the backup archives wo
archive_permissions: 0644 # Makes the backup archives world-readable
```
-## Storing configuration files
+### Storing configuration files
Please be informed that a backup does not store your configuration
-files. One reason for this is that your database contains encrypted
-information for two-factor authentication. Storing encrypted
+files. One reason for this is that your database contains encrypted
+information for two-factor authentication. Storing encrypted
information along with its key in the same place defeats the purpose
of using encryption in the first place!
If you use an Omnibus package please see the [instructions in the readme to backup your configuration](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#backup-and-restore-omnibus-gitlab-configuration).
If you have a cookbook installation there should be a copy of your configuration in Chef.
-If you have an installation from source, please consider backing up your `config/secrets.yml` file, `gitlab.yml` file, any SSL keys and certificates, and your [SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
+If you installed from source, please consider backing up your `config/secrets.yml` file, `gitlab.yml` file, any SSL keys and certificates, and your [SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
At the very **minimum** you should backup `/etc/gitlab/gitlab.rb` and
`/etc/gitlab/gitlab-secrets.json` (Omnibus), or
`/home/git/gitlab/config/secrets.yml` (source) to preserve your database
encryption key.
-## Restore a previously created backup
+### Configuring cron to make daily backups
+
+>**Note:**
+The following cron jobs do not [backup your GitLab configuration files](#storing-configuration-files)
+or [SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
+
+**For Omnibus installations**
+
+To schedule a cron job that backs up your repositories and GitLab metadata, use the root user:
+
+```
+sudo su -
+crontab -e
+```
+
+There, add the following line to schedule the backup for everyday at 2 AM:
+
+```
+0 2 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create CRON=1
+```
+
+You may also want to set a limited lifetime for backups to prevent regular
+backups using all your disk space. To do this add the following lines to
+`/etc/gitlab/gitlab.rb` and reconfigure:
+
+```
+# limit backup lifetime to 7 days - 604800 seconds
+gitlab_rails['backup_keep_time'] = 604800
+```
+
+Note that the `backup_keep_time` configuration option only manages local
+files. GitLab does not automatically prune old files stored in a third-party
+object storage (e.g., AWS S3) because the user may not have permission to list
+and delete files. We recommend that you configure the appropriate retention
+policy for your object storage. For example, you can configure [the S3 backup
+policy as described here](http://stackoverflow.com/questions/37553070/gitlab-omnibus-delete-backup-from-amazon-s3).
+
+**For installation from source**
+
+```
+cd /home/git/gitlab
+sudo -u git -H editor config/gitlab.yml # Enable keep_time in the backup section to automatically delete old backups
+sudo -u git crontab -e # Edit the crontab for the git user
+```
+
+Add the following lines at the bottom:
+
+```
+# Create a full backup of the GitLab repositories and SQL database every day at 4am
+0 4 * * * cd /home/git/gitlab && PATH=/usr/local/bin:/usr/bin:/bin bundle exec rake gitlab:backup:create RAILS_ENV=production CRON=1
+```
+
+The `CRON=1` environment setting tells the backup script to suppress all progress output if there are no errors.
+This is recommended to reduce cron spam.
+
+## Restore
+
+GitLab provides a simple command line interface to backup your whole installation,
+and is flexible enough to fit your needs.
+
+The [restore prerequisites section](#restore-prerequisites) includes crucial
+information. Make sure to read and test the whole restore process at least once
+before attempting to perform it in a production environment.
-You can only restore a backup to exactly the same version of GitLab that you created it on, for example 7.2.1.
+You can only restore a backup to **exactly the same version** of GitLab that
+you created it on, for example 9.1.0.
-### Prerequisites
+### Restore prerequisites
You need to have a working GitLab installation before you can perform
a restore. This is mainly because the system user performing the
@@ -248,13 +381,23 @@ the SQL database it needs to import data into ('gitlabhq_production').
All existing data will be either erased (SQL) or moved to a separate
directory (repositories, uploads).
-If some or all of your GitLab users are using two-factor authentication (2FA)
-then you must also make sure to restore `/etc/gitlab/gitlab.rb` and
-`/etc/gitlab/gitlab-secrets.json` (Omnibus), or
-`/home/git/gitlab/config/secrets.yml` (installations from source). Note that you
-need to run `gitlab-ctl reconfigure` after changing `gitlab-secrets.json`.
+To restore a backup, you will also need to restore `/etc/gitlab/gitlab-secrets.json`
+(for Omnibus packages) or `/home/git/gitlab/.secret` (for installations
+from source). This file contains the database encryption key,
+[CI secret variables](../ci/variables/README.md#secret-variables), and
+secret variables used for [two-factor authentication](../user/profile/account/two_factor_authentication.md).
+If you fail to restore this encryption key file along with the application data
+backup, users with two-factor authentication enabled and GitLab Runners will
+lose access to your GitLab server.
+
+Depending on your case, you might want to run the restore command with one or
+more of the following options:
+
+- `BACKUP=timestamp_of_backup` - Required if more than one backup exists.
+ Read what the [backup timestamp is about](#backup-timestamp).
+- `force=yes` - Do not ask if the authorized_keys file should get regenerated.
-### Installation from source
+### Restore for installation from source
```
# Stop processes that are connected to the database
@@ -263,13 +406,6 @@ sudo service gitlab stop
bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
-Options:
-
-```
-BACKUP=timestamp_of_backup (required if more than one backup exists)
-force=yes (do not ask if the authorized_keys file should get regenerated)
-```
-
Example output:
```
@@ -301,13 +437,13 @@ Restoring repositories:
Deleting tmp directories...[DONE]
```
-### Omnibus installations
+### Restore for Omnibus installations
This procedure assumes that:
-- You have installed the exact same version of GitLab Omnibus with which the
- backup was created
-- You have run `sudo gitlab-ctl reconfigure` at least once
+- You have installed the **exact same version** of GitLab Omnibus with which the
+ backup was created.
+- You have run `sudo gitlab-ctl reconfigure` at least once.
- GitLab is running. If not, start it using `sudo gitlab-ctl start`.
First make sure your backup tar file is in the backup directory described in the
@@ -315,7 +451,7 @@ First make sure your backup tar file is in the backup directory described in the
`/var/opt/gitlab/backups`.
```shell
-sudo cp 1393513186_gitlab_backup.tar /var/opt/gitlab/backups/
+sudo cp 1493107454_2017_04_25_9.1.0_gitlab_backup.tar /var/opt/gitlab/backups/
```
Stop the processes that are connected to the database. Leave the rest of GitLab
@@ -333,7 +469,7 @@ restore:
```shell
# This command will overwrite the contents of your GitLab database!
-sudo gitlab-rake gitlab:backup:restore BACKUP=1393513186
+sudo gitlab-rake gitlab:backup:restore BACKUP=1493107454_2017_04_25_9.1.0
```
Restart and check GitLab:
@@ -345,59 +481,7 @@ sudo gitlab-rake gitlab:check SANITIZE=true
If there is a GitLab version mismatch between your backup tar file and the installed
version of GitLab, the restore command will abort with an error. Install the
-[correct GitLab version](https://www.gitlab.com/downloads/archives/) and try again.
-
-## Configure cron to make daily backups
-
-### For installation from source:
-```
-cd /home/git/gitlab
-sudo -u git -H editor config/gitlab.yml # Enable keep_time in the backup section to automatically delete old backups
-sudo -u git crontab -e # Edit the crontab for the git user
-```
-
-Add the following lines at the bottom:
-
-```
-# Create a full backup of the GitLab repositories and SQL database every day at 4am
-0 4 * * * cd /home/git/gitlab && PATH=/usr/local/bin:/usr/bin:/bin bundle exec rake gitlab:backup:create RAILS_ENV=production CRON=1
-```
-
-The `CRON=1` environment setting tells the backup script to suppress all progress output if there are no errors.
-This is recommended to reduce cron spam.
-
-### For omnibus installations
-
-To schedule a cron job that backs up your repositories and GitLab metadata, use the root user:
-
-```
-sudo su -
-crontab -e
-```
-
-There, add the following line to schedule the backup for everyday at 2 AM:
-
-```
-0 2 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create CRON=1
-```
-
-You may also want to set a limited lifetime for backups to prevent regular
-backups using all your disk space. To do this add the following lines to
-`/etc/gitlab/gitlab.rb` and reconfigure:
-
-```
-# limit backup lifetime to 7 days - 604800 seconds
-gitlab_rails['backup_keep_time'] = 604800
-```
-
-Note that the `backup_keep_time` configuration option only manages local
-files. GitLab does not automatically prune old files stored in a third-party
-object storage (e.g. AWS S3) because the user may not have permission to list
-and delete files. We recommend that you configure the appropriate retention
-policy for your object storage. For example, you can configure [the S3 backup
-policy here as described here](http://stackoverflow.com/questions/37553070/gitlab-omnibus-delete-backup-from-amazon-s3).
-
-NOTE: This cron job does not [backup your omnibus-gitlab configuration](#backup-and-restore-omnibus-gitlab-configuration) or [SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
+[correct GitLab version](https://packages.gitlab.com/gitlab/) and try again.
## Alternative backup strategies
@@ -422,6 +506,19 @@ Example: LVM snapshots + rsync
If you are running GitLab on a virtualized server you can possibly also create VM snapshots of the entire GitLab server.
It is not uncommon however for a VM snapshot to require you to power down the server, so this approach is probably of limited practical use.
+## Additional notes
+
+This documentation is for GitLab Community and Enterprise Edition. We backup
+GitLab.com and make sure your data is secure, but you can't use these methods
+to export / backup your data yourself from GitLab.com.
+
+Issues are stored in the database. They can't be stored in Git itself.
+
+To migrate your repositories from one server to another with an up-to-date version of
+GitLab, you can use the [import rake task](import.md) to do a mass import of the
+repository. Note that if you do an import rake task, rather than a backup restore, you
+will have all your repositories, but not any other data.
+
## Troubleshooting
### Restoring database backup using omnibus packages outputs warnings
@@ -431,7 +528,6 @@ If you are using backup restore procedures you might encounter the following war
psql:/var/opt/gitlab/backups/db/database.sql:22: ERROR: must be owner of extension plpgsql
psql:/var/opt/gitlab/backups/db/database.sql:2931: WARNING: no privileges could be revoked for "public" (two occurrences)
psql:/var/opt/gitlab/backups/db/database.sql:2933: WARNING: no privileges were granted for "public" (two occurrences)
-
```
Be advised that, backup is successfully restored in spite of these warnings.
@@ -440,14 +536,3 @@ The rake task runs this as the `gitlab` user which does not have the superuser a
Those objects have no influence on the database backup/restore but they give this annoying warning.
For more information see similar questions on postgresql issue tracker[here](http://www.postgresql.org/message-id/201110220712.30886.adrian.klaver@gmail.com) and [here](http://www.postgresql.org/message-id/2039.1177339749@sss.pgh.pa.us) as well as [stack overflow](http://stackoverflow.com/questions/4368789/error-must-be-owner-of-language-plpgsql).
-
-## Note
-This documentation is for GitLab CE.
-We backup GitLab.com and make sure your data is secure, but you can't use these methods to export / backup your data yourself from GitLab.com.
-
-Issues are stored in the database. They can't be stored in Git itself.
-
-To migrate your repositories from one server to another with an up-to-date version of
-GitLab, you can use the [import rake task](import.md) to do a mass import of the
-repository. Note that if you do an import rake task, rather than a backup restore, you
-will have all your repositories, but not any other data.
diff --git a/doc/raketasks/check.md b/doc/raketasks/check.md
index 3ff3fee6a40..f7f6a40cd04 100644
--- a/doc/raketasks/check.md
+++ b/doc/raketasks/check.md
@@ -1,63 +1,3 @@
# Check Rake Tasks
-## Repository Integrity
-
-Even though Git is very resilient and tries to prevent data integrity issues,
-there are times when things go wrong. The following Rake tasks intend to
-help GitLab administrators diagnose problem repositories so they can be fixed.
-
-There are 3 things that are checked to determine integrity.
-
-1. Git repository file system check ([git fsck](https://git-scm.com/docs/git-fsck)).
- This step verifies the connectivity and validity of objects in the repository.
-1. Check for `config.lock` in the repository directory.
-1. Check for any branch/references lock files in `refs/heads`.
-
-It's important to note that the existence of `config.lock` or reference locks
-alone do not necessarily indicate a problem. Lock files are routinely created
-and removed as Git and GitLab perform operations on the repository. They serve
-to prevent data integrity issues. However, if a Git operation is interrupted these
-locks may not be cleaned up properly.
-
-The following symptoms may indicate a problem with repository integrity. If users
-experience these symptoms you may use the rake tasks described below to determine
-exactly which repositories are causing the trouble.
-
-- Receiving an error when trying to push code - `remote: error: cannot lock ref`
-- A 500 error when viewing the GitLab dashboard or when accessing a specific project.
-
-### Check all GitLab repositories
-
-This task loops through all repositories on the GitLab server and runs the
-3 integrity checks described previously.
-
-```
-# omnibus-gitlab
-sudo gitlab-rake gitlab:repo:check
-
-# installation from source
-bundle exec rake gitlab:repo:check RAILS_ENV=production
-```
-
-### Check repositories for a specific user
-
-This task checks all repositories that a specific user has access to. This is important
-because sometimes you know which user is experiencing trouble but you don't know
-which project might be the cause.
-
-If the rake task is executed without brackets at the end, you will be prompted
-to enter a username.
-
-```bash
-# omnibus-gitlab
-sudo gitlab-rake gitlab:user:check_repos
-sudo gitlab-rake gitlab:user:check_repos[<username>]
-
-# installation from source
-bundle exec rake gitlab:user:check_repos RAILS_ENV=production
-bundle exec rake gitlab:user:check_repos[<username>] RAILS_ENV=production
-```
-
-Example output:
-
-![gitlab:user:check_repos output](check_repos_output.png)
+This document was moved to [administration/raketasks/check](../administration/raketasks/check.md).
diff --git a/doc/raketasks/check_repos_output.png b/doc/raketasks/check_repos_output.png
deleted file mode 100644
index 1f632566b00..00000000000
--- a/doc/raketasks/check_repos_output.png
+++ /dev/null
Binary files differ
diff --git a/doc/raketasks/features.md b/doc/raketasks/features.md
index f9a46193547..fee49cc27cc 100644
--- a/doc/raketasks/features.md
+++ b/doc/raketasks/features.md
@@ -7,7 +7,7 @@ This command will enable the namespaces feature introduced in v4.0. It will move
Note:
- Because the **repository location will change**, you will need to **update all your git URLs** to point to the new location.
-- Username can be changed at [Profile / Account](/profile/account)
+- Username can be changed at **Profile ➔ Account**.
**Example:**
diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md
index 315cb56a089..266aeb7d60e 100644
--- a/doc/raketasks/maintenance.md
+++ b/doc/raketasks/maintenance.md
@@ -1,188 +1,3 @@
-# Maintenance
+# Maintenance Rake Tasks
-## Gather information about GitLab and the system it runs on
-
-This command gathers information about your GitLab installation and the System it runs on. These may be useful when asking for help or reporting issues.
-
-```
-# omnibus-gitlab
-sudo gitlab-rake gitlab:env:info
-
-# installation from source
-bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-Example output:
-
-```
-System information
-System: Debian 7.8
-Current User: git
-Using RVM: no
-Ruby Version: 2.1.5p273
-Gem Version: 2.4.3
-Bundler Version: 1.7.6
-Rake Version: 10.3.2
-Sidekiq Version: 2.17.8
-
-GitLab information
-Version: 7.7.1
-Revision: 41ab9e1
-Directory: /home/git/gitlab
-DB Adapter: postgresql
-URL: https://gitlab.example.com
-HTTP Clone URL: https://gitlab.example.com/some-project.git
-SSH Clone URL: git@gitlab.example.com:some-project.git
-Using LDAP: no
-Using Omniauth: no
-
-GitLab Shell
-Version: 2.4.1
-Repositories: /home/git/repositories/
-Hooks: /home/git/gitlab-shell/hooks/
-Git: /usr/bin/git
-```
-
-## Check GitLab configuration
-
-Runs the following rake tasks:
-
-- `gitlab:gitlab_shell:check`
-- `gitlab:sidekiq:check`
-- `gitlab:app:check`
-
-It will check that each component was setup according to the installation guide and suggest fixes for issues found.
-
-You may also have a look at our [Trouble Shooting Guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide).
-
-```
-# omnibus-gitlab
-sudo gitlab-rake gitlab:check
-
-# installation from source
-bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-NOTE: Use SANITIZE=true for gitlab:check if you want to omit project names from the output.
-
-Example output:
-
-```
-Checking Environment ...
-
-Git configured for git user? ... yes
-Has python2? ... yes
-python2 is supported version? ... yes
-
-Checking Environment ... Finished
-
-Checking GitLab Shell ...
-
-GitLab Shell version? ... OK (1.2.0)
-Repo base directory exists? ... yes
-Repo base directory is a symlink? ... no
-Repo base owned by git:git? ... yes
-Repo base access is drwxrws---? ... yes
-post-receive hook up-to-date? ... yes
-post-receive hooks in repos are links: ... yes
-
-Checking GitLab Shell ... Finished
-
-Checking Sidekiq ...
-
-Running? ... yes
-
-Checking Sidekiq ... Finished
-
-Checking GitLab ...
-
-Database config exists? ... yes
-Database is SQLite ... no
-All migrations up? ... yes
-GitLab config exists? ... yes
-GitLab config outdated? ... no
-Log directory writable? ... yes
-Tmp directory writable? ... yes
-Init script exists? ... yes
-Init script up-to-date? ... yes
-Redis version >= 2.0.0? ... yes
-
-Checking GitLab ... Finished
-```
-
-## Rebuild authorized_keys file
-
-In some case it is necessary to rebuild the `authorized_keys` file.
-
-For Omnibus-packages:
-```
-sudo gitlab-rake gitlab:shell:setup
-```
-
-For installations from source:
-```
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:shell:setup RAILS_ENV=production
-```
-
-```
-This will rebuild an authorized_keys file.
-You will lose any data stored in authorized_keys file.
-Do you want to continue (yes/no)? yes
-```
-
-## Clear redis cache
-
-If for some reason the dashboard shows wrong information you might want to
-clear Redis' cache.
-
-For Omnibus-packages:
-```
-sudo gitlab-rake cache:clear
-```
-
-For installations from source:
-```
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-## Precompile the assets
-
-Sometimes during version upgrades you might end up with some wrong CSS or
-missing some icons. In that case, try to precompile the assets again.
-
-Note that this only applies to source installations and does NOT apply to
-omnibus packages.
-
-For installations from source:
-```
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
-```
-
-For omnibus versions, the unoptimized assets (JavaScript, CSS) are frozen at
-the release of upstream GitLab. The omnibus version includes optimized versions
-of those assets. Unless you are modifying the JavaScript / CSS code on your
-production machine after installing the package, there should be no reason to redo
-rake assets:precompile on the production machine. If you suspect that assets
-have been corrupted, you should reinstall the omnibus package.
-
-## Tracking Deployments
-
-GitLab provides a Rake task that lets you track deployments in GitLab
-Performance Monitoring. This Rake task simply stores the current GitLab version
-in the GitLab Performance Monitoring database.
-
-For Omnibus-packages:
-
-```
-sudo gitlab-rake gitlab:track_deployment
-```
-
-For installations from source:
-
-```
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:track_deployment RAILS_ENV=production
-```
+This document was moved to [administration/raketasks/maintenance](../administration/raketasks/maintenance.md).
diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md
index 8a5e2d6e16b..3ae46019daf 100644
--- a/doc/raketasks/user_management.md
+++ b/doc/raketasks/user_management.md
@@ -70,3 +70,97 @@ sudo gitlab-rake gitlab:two_factor:disable_for_all_users
# installation from source
bundle exec rake gitlab:two_factor:disable_for_all_users RAILS_ENV=production
```
+
+## Rotate Two-factor Authentication (2FA) encryption key
+
+GitLab stores the secret data enabling 2FA to work in an encrypted database
+column. The encryption key for this data is known as `otp_key_base`, and is
+stored in `config/secrets.yml`.
+
+
+If that file is leaked, but the individual 2FA secrets have not, it's possible
+to re-encrypt those secrets with a new encryption key. This allows you to change
+the leaked key without forcing all users to change their 2FA details.
+
+First, look up the old key. This is in the `config/secrets.yml` file, but
+**make sure you're working with the production section**. The line you're
+interested in will look like this:
+
+```yaml
+production:
+ otp_key_base: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+```
+
+Next, generate a new secret:
+
+```
+# omnibus-gitlab
+sudo gitlab-rake secret
+
+# installation from source
+bundle exec rake secret RAILS_ENV=production
+```
+
+Now you need to stop the GitLab server, back up the existing secrets file and
+update the database:
+
+```
+# omnibus-gitlab
+sudo gitlab-ctl stop
+sudo cp config/secrets.yml config/secrets.yml.bak
+sudo gitlab-rake gitlab:two_factor:rotate_key:apply filename=backup.csv old_key=<old key> new_key=<new key>
+
+# installation from source
+sudo /etc/init.d/gitlab stop
+cp config/secrets.yml config/secrets.yml.bak
+bundle exec rake gitlab:two_factor:rotate_key:apply filename=backup.csv old_key=<old key> new_key=<new key> RAILS_ENV=production
+```
+
+The `<old key>` value can be read from `config/secrets.yml`; `<new key>` was
+generated earlier. The **encrypted** values for the user 2FA secrets will be
+written to the specified `filename` - you can use this to rollback in case of
+error.
+
+Finally, change `config/secrets.yml` to set `otp_key_base` to `<new key>` and
+restart. Again, make sure you're operating in the **production** section.
+
+```
+# omnibus-gitlab
+sudo gitlab-ctl start
+
+# installation from source
+sudo /etc/init.d/gitlab start
+```
+
+If there are any problems (perhaps using the wrong value for `old_key`), you can
+restore your backup of `config/secrets.yml` and rollback the changes:
+
+```
+# omnibus-gitlab
+sudo gitlab-ctl stop
+sudo gitlab-rake gitlab:two_factor:rotate_key:rollback filename=backup.csv
+sudo cp config/secrets.yml.bak config/secrets.yml
+sudo gitlab-ctl start
+
+# installation from source
+sudo /etc/init.d/gitlab start
+bundle exec rake gitlab:two_factor:rotate_key:rollback filename=backup.csv RAILS_ENV=production
+cp config/secrets.yml.bak config/secrets.yml
+sudo /etc/init.d/gitlab start
+
+```
+
+## Clear authentication tokens for all users. Important! Data loss!
+
+Clear authentication tokens for all users in the GitLab database. This
+task is useful if your users' authentication tokens might have been exposed in
+any way. All the existing tokens will become invalid, and new tokens are
+automatically generated upon sign-in or user modification.
+
+```
+# omnibus-gitlab
+sudo gitlab-rake gitlab:users:clear_all_authentication_tokens
+
+# installation from source
+bundle exec rake gitlab:users:clear_all_authentication_tokens RAILS_ENV=production
+```
diff --git a/doc/security/img/two_factor_authentication_group_settings.png b/doc/security/img/two_factor_authentication_group_settings.png
new file mode 100644
index 00000000000..a1b3c58bfdc
--- /dev/null
+++ b/doc/security/img/two_factor_authentication_group_settings.png
Binary files differ
diff --git a/doc/security/img/two_factor_authentication_settings.png b/doc/security/img/two_factor_authentication_settings.png
index 6af5feabb13..6d89be1eb04 100644
--- a/doc/security/img/two_factor_authentication_settings.png
+++ b/doc/security/img/two_factor_authentication_settings.png
Binary files differ
diff --git a/doc/security/two_factor_authentication.md b/doc/security/two_factor_authentication.md
index c8499380c18..f02f7b807cf 100644
--- a/doc/security/two_factor_authentication.md
+++ b/doc/security/two_factor_authentication.md
@@ -8,7 +8,7 @@ their phone.
You can read more about it here:
[Two-factor Authentication (2FA)](../profile/two_factor_authentication.md)
-## Enabling 2FA
+## Enforcing 2FA for all users
Users on GitLab, can enable it without any admin's intervention. If you want to
enforce everyone to setup 2FA, you can choose from two different ways:
@@ -28,6 +28,21 @@ period to `0`.
---
+## Enforcing 2FA for all users in a group
+
+If you want to enforce 2FA only for certain groups, you can enable it in the
+group settings and specify a grace period as above. To change this setting you
+need to be administrator or owner of the group.
+
+If there are multiple 2FA requirements (i.e. group + all users, or multiple
+groups) the shortest grace period will be used.
+
+---
+
+![Two factor authentication group settings](img/two_factor_authentication_group_settings.png)
+
+---
+
## Disabling 2FA for everyone
There may be some special situations where you want to disable 2FA for everyone
diff --git a/doc/security/webhooks.md b/doc/security/webhooks.md
index bb46aebf4b5..faabc53ce72 100644
--- a/doc/security/webhooks.md
+++ b/doc/security/webhooks.md
@@ -2,7 +2,7 @@
If you have non-GitLab web services running on your GitLab server or within its local network, these may be vulnerable to exploitation via Webhooks.
-With [Webhooks](../web_hooks/web_hooks.md), you and your project masters and owners can set up URLs to be triggered when specific things happen to projects. Normally, these requests are sent to external web services specifically set up for this purpose, that process the request and its attached data in some appropriate way.
+With [Webhooks](../user/project/integrations/webhooks.md), you and your project masters and owners can set up URLs to be triggered when specific things happen to projects. Normally, these requests are sent to external web services specifically set up for this purpose, that process the request and its attached data in some appropriate way.
Things get hairy, however, when a Webhook is set up with a URL that doesn't point to an external, but to an internal service, that may do something completely unintended when the webhook is triggered and the POST request is sent.
@@ -10,4 +10,4 @@ Because Webhook requests are made by the GitLab server itself, these have comple
If a web service does not require authentication, Webhooks can be used to trigger destructive commands by getting the GitLab server to make POST requests to endpoints like "http://localhost:123/some-resource/delete".
-To prevent this type of exploitation from happening, make sure that you are aware of every web service GitLab could potentially have access to, and that all of these are set up to require authentication for every potentially destructive command. Enabling authentication but leaving a default password is not enough. \ No newline at end of file
+To prevent this type of exploitation from happening, make sure that you are aware of every web service GitLab could potentially have access to, and that all of these are set up to require authentication for every potentially destructive command. Enabling authentication but leaving a default password is not enough.
diff --git a/doc/ssh/README.md b/doc/ssh/README.md
index d6a0979f6ec..cf28f1a2eca 100644
--- a/doc/ssh/README.md
+++ b/doc/ssh/README.md
@@ -1,132 +1,206 @@
# SSH
-## SSH keys
+Git is a distributed version control system, which means you can work locally
+but you can also share or "push" your changes to other servers.
+Before you can push your changes to a GitLab server
+you need a secure communication channel for sharing information.
-An SSH key allows you to establish a secure connection between your
-computer and GitLab. Before generating an SSH key in your shell, check if your system
-already has one by running the following command:
+The SSH protocol provides this security and allows you to authenticate to the
+GitLab remote server without supplying your username or password each time.
+
+For a more detailed explanation of how the SSH protocol works, we advise you to
+read [this nice tutorial by DigitalOcean](https://www.digitalocean.com/community/tutorials/understanding-the-ssh-encryption-and-connection-process).
+
+## Locating an existing SSH key pair
+
+Before generating a new SSH key pair check if your system already has one
+at the default location by opening a shell, or Command Prompt on Windows,
+and running the following command:
+
+**Windows Command Prompt:**
-**Windows Command Line:**
```bash
type %userprofile%\.ssh\id_rsa.pub
```
-**GNU/Linux/Mac/PowerShell:**
+
+**Git Bash on Windows / GNU/Linux / macOS / PowerShell:**
+
```bash
cat ~/.ssh/id_rsa.pub
```
-If you see a long string starting with `ssh-rsa`, you can skip the `ssh-keygen` step.
+If you see a string starting with `ssh-rsa` you already have an SSH key pair
+and you can skip the generate portion of the next section and skip to the copy
+to clipboard step.
+If you don't see the string or would like to generate a SSH key pair with a
+custom name continue onto the next step.
-To generate a new SSH key, use the following command:
-```bash
-ssh-keygen -t rsa -C "$your_email"
-```
-This command will prompt you for a location and filename to store the key
-pair and for a password. When prompted for the location and filename, just
-press enter to use the default. If you use a different name, the key will not
-be used automatically.
+>
+**Note:** Public SSH key may also be named as follows:
+- `id_dsa.pub`
+- `id_ecdsa.pub`
+- `id_ed25519.pub`
-Note: It is a best practice to use a password for an SSH key, but it is not
-required and you can skip creating a password by pressing enter.
+## Generating a new SSH key pair
-If you want to change the password of your key later, you can use the following
-command: `ssh-keygen -p <keyname>`
+1. To generate a new SSH key pair, use the following command:
-Use the command below to show your public key:
+ **Git Bash on Windows / GNU/Linux / macOS:**
-**Windows Command Line:**
-```bash
-type %userprofile%\.ssh\id_rsa.pub
-```
-**GNU/Linux/Mac/PowerShell:**
-```bash
-cat ~/.ssh/id_rsa.pub
-```
+ ```bash
+ ssh-keygen -t rsa -C "your.email@example.com" -b 4096
+ ```
-Copy-paste the key to the 'My SSH Keys' section under the 'SSH' tab in your
-user profile. Please copy the complete key starting with `ssh-rsa` and ending
-with your username and host.
+ **Windows:**
-To copy your public key to the clipboard, use the code below. Depending on your
-OS you'll need to use a different command:
+ Alternatively on Windows you can download
+ [PuttyGen](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html)
+ and follow [this documentation article][winputty] to generate a SSH key pair.
-**Windows Command Line:**
-```bash
-type %userprofile%\.ssh\id_rsa.pub | clip
-```
+1. Next, you will be prompted to input a file path to save your SSH key pair to.
+
+ If you don't already have an SSH key pair use the suggested path by pressing
+ enter. Using the suggested path will normally allow your SSH client
+ to automatically use the SSH key pair with no additional configuration.
+
+ If you already have a SSH key pair with the suggested file path, you will need
+ to input a new file path and declare what host this SSH key pair will be used
+ for in your `.ssh/config` file, see [**Working with non-default SSH key pair paths**](#working-with-non-default-ssh-key-pair-paths)
+ for more information.
+
+1. Once you have input a file path you will be prompted to input a password to
+ secure your SSH key pair. It is a best practice to use a password for an SSH
+ key pair, but it is not required and you can skip creating a password by
+ pressing enter.
+
+ >**Note:**
+ If you want to change the password of your SSH key pair, you can use
+ `ssh-keygen -p <keyname>`.
+
+1. The next step is to copy the public SSH key as we will need it afterwards.
+
+ To copy your public SSH key to the clipboard, use the appropriate code below:
+
+ **macOS:**
+
+ ```bash
+ pbcopy < ~/.ssh/id_rsa.pub
+ ```
+
+ **GNU/Linux (requires the xclip package):**
+
+ ```bash
+ xclip -sel clip < ~/.ssh/id_rsa.pub
+ ```
+
+ **Windows Command Line:**
+
+ ```bash
+ type %userprofile%\.ssh\id_rsa.pub | clip
+ ```
+
+ **Git Bash on Windows / Windows PowerShell:**
+
+ ```bash
+ cat ~/.ssh/id_rsa.pub | clip
+ ```
+
+1. The final step is to add your public SSH key to GitLab.
+
+ Navigate to the 'SSH Keys' tab in your 'Profile Settings'.
+ Paste your key in the 'Key' section and give it a relevant 'Title'.
+ Use an identifiable title like 'Work Laptop - Windows 7' or
+ 'Home MacBook Pro 15'.
+
+ If you manually copied your public SSH key make sure you copied the entire
+ key starting with `ssh-rsa` and ending with your email.
+
+1. Optionally you can test your setup by running `ssh -T git@example.com`
+ (replacing `example.com` with your GitLab domain) and verifying that you
+ receive a `Welcome to GitLab` message.
+
+## Working with non-default SSH key pair paths
+
+If you used a non-default file path for your GitLab SSH key pair,
+you must configure your SSH client to find your GitLab private SSH key
+for connections to your GitLab server (perhaps `gitlab.com`).
+
+For your current terminal session you can do so using the following commands
+(replacing `other_id_rsa` with your private SSH key):
+
+**Git Bash on Windows / GNU/Linux / macOS:**
-**Windows PowerShell:**
```bash
-cat ~/.ssh/id_rsa.pub | clip
+eval $(ssh-agent -s)
+ssh-add ~/.ssh/other_id_rsa
```
-**Mac:**
-```bash
-pbcopy < ~/.ssh/id_rsa.pub
+To retain these settings you'll need to save them to a configuration file.
+For OpenSSH clients this is configured in the `~/.ssh/config` file for some
+operating systems.
+Below are two example host configurations using their own SSH key:
+
```
+# GitLab.com server
+Host gitlab.com
+RSAAuthentication yes
+IdentityFile ~/.ssh/config/private-key-filename-01
-**GNU/Linux (requires xclip):**
-```bash
-xclip -sel clip < ~/.ssh/id_rsa.pub
+# Private GitLab server
+Host gitlab.company.com
+RSAAuthentication yes
+IdentityFile ~/.ssh/config/private-key-filename
```
+Due to the wide variety of SSH clients and their very large number of
+configuration options, further explanation of these topics is beyond the scope
+of this document.
+
+Public SSH keys need to be unique, as they will bind to your account.
+Your SSH key is the only identifier you'll have when pushing code via SSH.
+That's why it needs to uniquely map to a single user.
+
## Deploy keys
-Deploy keys allow read-only access to multiple projects with a single SSH
-key.
+Deploy keys allow read-only or read-write (if enabled) access to one or
+multiple projects with a single SSH key pair.
This is really useful for cloning repositories to your Continuous
Integration (CI) server. By using deploy keys, you don't have to setup a
dummy user account.
If you are a project master or owner, you can add a deploy key in the
-project settings under the section 'Deploy Keys'. Press the 'New Deploy
-Key' button and upload a public SSH key. After this, the machine that uses
-the corresponding private key has read-only access to the project.
+project settings under the section 'Repository'. Specify a title for the new
+deploy key and paste a public SSH key. After this, the machine that uses
+the corresponding private SSH key has read-only or read-write (if enabled)
+access to the project.
-You can't add the same deploy key twice with the 'New Deploy Key' option.
+You can't add the same deploy key twice using the form.
If you want to add the same key to another project, please enable it in the
list that says 'Deploy keys from projects available to you'. All the deploy
keys of all the projects you have access to are available. This project
access can happen through being a direct member of the project, or through
-a group. See `def accessible_deploy_keys` in `app/models/user.rb` for more
-information.
+a group.
-Deploy keys can be shared between projects, you just need to add them to each project.
+Deploy keys can be shared between projects, you just need to add them to each
+project.
## Applications
### Eclipse
-How to add your ssh key to Eclipse: https://wiki.eclipse.org/EGit/User_Guide#Eclipse_SSH_Configuration
-
-## Tip: Non-default OpenSSH key file names or locations
+How to add your SSH key to Eclipse: https://wiki.eclipse.org/EGit/User_Guide#Eclipse_SSH_Configuration
-If, for whatever reason, you decide to specify a non-default location and filename for your GitLab SSH key pair, you must configure your SSH client to find your GitLab SSH private key for connections to your GitLab server (perhaps gitlab.com). For OpenSSH clients, this is handled in the `~/.ssh/config` file with a stanza similar to the following:
-
-```
-#
-# Main gitlab.com server
-#
-Host gitlab.com
-RSAAuthentication yes
-IdentityFile ~/my-ssh-key-directory/my-gitlab-private-key-filename
-User mygitlabusername
-```
-
-Another example
-```
-#
-# Our company's internal GitLab server
-#
-Host my-gitlab.company.com
-RSAAuthentication yes
-IdentityFile ~/my-ssh-key-directory/company-com-private-key-filename
-```
+[winputty]: https://the.earth.li/~sgtatham/putty/0.67/htmldoc/Chapter8.html#pubkey-puttygen
-Note in the gitlab.com example above a username was specified to override the default chosen by OpenSSH (your local username). This is only required if your local and remote usernames differ.
+## Troubleshooting
-Due to the wide variety of SSH clients and their very large number of configuration options, further explanation of these topics is beyond the scope of this document.
+If on Git clone you are prompted for a password like `git@gitlab.com's password:`
+something is wrong with your SSH setup.
-Public SSH keys need to be unique, as they will bind to your account. Your SSH key is the only identifier you'll
-have when pushing code via SSH. That's why it needs to uniquely map to a single user. \ No newline at end of file
+- Ensure that you generated your SSH key pair correctly and added the public SSH
+ key to your GitLab profile
+- Try manually registering your private SSH key using `ssh-agent` as documented
+ earlier in this document
+- Try to debug the connection by running `ssh -Tv git@example.com`
+ (replacing `example.com` with your GitLab domain)
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index c44930a4ceb..583ec5522fd 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -1,6 +1,6 @@
# System hooks
-Your GitLab instance can perform HTTP POST requests on the following events: `project_create`, `project_destroy`, `project_rename`, `project_transfer`, `user_add_to_team`, `user_remove_from_team`, `user_create`, `user_destroy`, `key_create`, `key_destroy`, `group_create`, `group_destroy`, `user_add_to_group` and `user_remove_from_group`.
+Your GitLab instance can perform HTTP POST requests on the following events: `project_create`, `project_destroy`, `project_rename`, `project_transfer`, `project_update`, `user_add_to_team`, `user_remove_from_team`, `user_create`, `user_destroy`, `key_create`, `key_destroy`, `group_create`, `group_destroy`, `user_add_to_group` and `user_remove_from_group`.
System hooks can be used, e.g. for logging or changing information in a LDAP server.
@@ -88,6 +88,23 @@ X-Gitlab-Event: System Hook
}
```
+**Project updated:**
+
+```json
+{
+ "created_at": "2012-07-21T07:30:54Z",
+ "updated_at": "2012-07-21T07:38:22Z",
+ "event_name": "project_update",
+ "name": "StoreCloud",
+ "owner_email": "johnsmith@gmail.com",
+ "owner_name": "John Smith",
+ "path": "storecloud",
+ "path_with_namespace": "jsmith/storecloud",
+ "project_id": 74,
+ "project_visibility": "private",
+}
+```
+
**New Team Member:**
```json
@@ -249,7 +266,8 @@ X-Gitlab-Event: System Hook
## Push events
-Triggered when you push to the repository except when pushing tags.
+Triggered when you push to the repository, except when pushing tags.
+It generates one event per modified branch.
**Request header**:
@@ -296,14 +314,26 @@ X-Gitlab-Event: System Hook
"git_ssh_url":"git@example.com:mike/diaspora.git",
"visibility_level":0
},
- "commits": [],
- "total_commits_count": 0
+ "commits": [
+ {
+ "id": "c5feabde2d8cd023215af4d2ceeb7a64839fc428",
+ "message": "Add simple search to projects in public area",
+ "timestamp": "2013-05-13T18:18:08+00:00",
+ "url": "https://dev.gitlab.org/gitlab/gitlabhq/commit/c5feabde2d8cd023215af4d2ceeb7a64839fc428",
+ "author": {
+ "name": "Dmitriy Zaporozhets",
+ "email": "dmitriy.zaporozhets@gmail.com"
+ }
+ }
+ ],
+ "total_commits_count": 1
}
```
## Tag events
Triggered when you create (or delete) tags to the repository.
+It generates one event per modified tag.
**Request header**:
@@ -353,3 +383,49 @@ X-Gitlab-Event: System Hook
"total_commits_count": 0
}
```
+## Repository Update events
+
+Triggered only once when you push to the repository (including tags).
+
+**Request header**:
+
+```
+X-Gitlab-Event: System Hook
+```
+
+**Request body:**
+
+```json
+{
+ "event_name": "repository_update",
+ "user_id": 1,
+ "user_name": "John Smith",
+ "user_email": "admin@example.com",
+ "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
+ "project_id": 1,
+ "project": {
+ "name":"Example",
+ "description":"",
+ "web_url":"http://example.com/jsmith/example",
+ "avatar_url":null,
+ "git_ssh_url":"git@example.com:jsmith/example.git",
+ "git_http_url":"http://example.com/jsmith/example.git",
+ "namespace":"Jsmith",
+ "visibility_level":0,
+ "path_with_namespace":"jsmith/example",
+ "default_branch":"master",
+ "homepage":"http://example.com/jsmith/example",
+ "url":"git@example.com:jsmith/example.git",
+ "ssh_url":"git@example.com:jsmith/example.git",
+ "http_url":"http://example.com/jsmith/example.git",
+ },
+ "changes": [
+ {
+ "before":"8205ea8d81ce0c6b90fbe8280d118cc9fdad6130",
+ "after":"4045ea7a3df38697b3730a20fb73c8bed8a3e69e",
+ "ref":"refs/heads/master"
+ }
+ ],
+ "refs":["refs/heads/master"]
+}
+```
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
new file mode 100644
index 00000000000..0c0d482499a
--- /dev/null
+++ b/doc/topics/authentication/index.md
@@ -0,0 +1,48 @@
+# Authentication
+
+This page gathers all the resources for the topic **Authentication** within GitLab.
+
+## GitLab users
+
+- [SSH](../../ssh/README.md)
+- [Two-Factor Authentication (2FA)](../../user/profile/account/two_factor_authentication.md#two-factor-authentication)
+- **Articles:**
+ - [Support for Universal 2nd Factor Authentication - YubiKeys](https://about.gitlab.com/2016/06/22/gitlab-adds-support-for-u2f/)
+ - [Security Webcast with Yubico](https://about.gitlab.com/2016/08/31/gitlab-and-yubico-security-webcast/)
+- **Integrations:**
+ - [GitLab as OAuth2 authentication service provider](../../integration/oauth_provider.md#introduction-to-oauth)
+
+## GitLab administrators
+
+- [LDAP (Community Edition)](../../administration/auth/ldap.md)
+- [LDAP (Enterprise Edition)](https://docs.gitlab.com/ee/administration/auth/ldap-ee.html)
+- [Enforce Two-factor Authentication (2FA)](../../security/two_factor_authentication.md#enforce-two-factor-authentication-2fa)
+- **Articles:**
+ - [How to Configure LDAP with GitLab CE](../../articles/how_to_configure_ldap_gitlab_ce/index.md)
+ - [How to Configure LDAP with GitLab EE](https://docs.gitlab.com/ee/articles/how_to_configure_ldap_gitlab_ee/)
+ - [Feature Highlight: LDAP Integration](https://about.gitlab.com/2014/07/10/feature-highlight-ldap-sync/)
+ - [Debugging LDAP](https://about.gitlab.com/handbook/support/workflows/ldap/debugging_ldap.html)
+- **Integrations:**
+ - [OmniAuth](../../integration/omniauth.md)
+ - [Authentiq OmniAuth Provider](../../administration/auth/authentiq.md#authentiq-omniauth-provider)
+ - [Atlassian Crowd OmniAuth Provider](../../administration/auth/crowd.md)
+ - [CAS OmniAuth Provider](../../integration/cas.md)
+ - [SAML OmniAuth Provider](../../integration/saml.md)
+ - [Okta SSO provider](../../administration/auth/okta.md)
+ - [Kerberos integration (GitLab EE)](https://docs.gitlab.com/ee/integration/kerberos.html)
+
+## API
+
+- [OAuth 2 Tokens](../../api/README.md#oauth-2-tokens)
+- [Private Tokens](../../api/README.md#private-tokens)
+- [Impersonation tokens](../../api/README.md#impersonation-tokens)
+- [GitLab as an OAuth2 provider](../../api/oauth2.md#gitlab-as-an-oauth2-provider)
+- [GitLab Runner API - Authentication](../../api/ci/runners.md#authentication)
+
+## Third-party resources
+
+- [Kanboard Plugin GitLab Authentication](https://kanboard.net/plugin/gitlab-auth)
+- [Jenkins GitLab OAuth Plugin](https://wiki.jenkins-ci.org/display/JENKINS/GitLab+OAuth+Plugin)
+- [Setup Gitlab CE with Active Directory authentication](https://www.caseylabs.com/setup-gitlab-ce-with-active-directory-authentication/)
+- [How to customize GitLab to support OpenID authentication](http://eric.van-der-vlist.com/blog/2013/11/23/how-to-customize-gitlab-to-support-openid-authentication/)
+- [Openshift - Configuring Authentication and User Agent](https://docs.openshift.org/latest/install_config/configuring_authentication.html#GitLab)
diff --git a/doc/topics/git/index.md b/doc/topics/git/index.md
new file mode 100644
index 00000000000..604f9375714
--- /dev/null
+++ b/doc/topics/git/index.md
@@ -0,0 +1,66 @@
+# Git documentation
+
+Git is a [free and open source](https://git-scm.com/about/free-and-open-source)
+distributed version control system designed to handle everything from small to
+very large projects with speed and efficiency.
+
+[GitLab](https://about.gitlab.com) is a Git-based fully integrated platform for
+software development. Besides Git's functionalities, GitLab has a lot of
+powerful [features](https://about.gitlab.com/features/) to enhance your
+[workflow](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/).
+
+We've gathered some resources to help you to get the best from Git with GitLab.
+
+## Getting started
+
+- [Git concepts](../../university/training/user_training.md#git-concepts)
+- [Start using Git on the command line](../../gitlab-basics/start-using-git.md)
+- [Command Line basic commands](../../gitlab-basics/command-line-commands.md)
+- [GitLab Git Cheat Sheet (download)](https://gitlab.com/gitlab-com/marketing/raw/master/design/print/git-cheatsheet/print-pdf/git-cheatsheet.pdf)
+- Commits
+ - [Revert a commit](../../user/project/merge_requests/revert_changes.md#reverting-a-commit)
+ - [Cherry-picking a commit](../../user/project/merge_requests/cherry_pick_changes.md#cherry-picking-a-commit)
+ - [Squashing commits](../../workflow/gitlab_flow.md#squashing-commits-with-rebase)
+- **Articles:**
+ - [How to install Git](../../articles/how_to_install_git/index.md)
+ - [Git Tips & Tricks](https://about.gitlab.com/2016/12/08/git-tips-and-tricks/)
+ - [Eight Tips to help you work better with Git](https://about.gitlab.com/2015/02/19/8-tips-to-help-you-work-better-with-git/)
+- **Presentations:**
+ - [GLU Course: About Version Control](https://docs.google.com/presentation/d/16sX7hUrCZyOFbpvnrAFrg6tVO5_yT98IgdAqOmXwBho/edit?usp=sharing)
+- **Third-party resources:**
+ - What is [Git](https://git-scm.com)
+ - [Version control](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control)
+ - [Getting Started - Git Basics](https://git-scm.com/book/en/v2/Getting-Started-Git-Basics)
+ - [Getting Started - Installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
+ - [Git on the Server - GitLab](https://git-scm.com/book/en/v2/Git-on-the-Server-GitLab)
+
+## Branching strategies
+
+- **Articles:**
+ - [GitLab Flow](https://about.gitlab.com/2014/09/29/gitlab-flow/)
+- **Third-party resources:**
+ - [Git Branching - Branches in a Nutshell](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell)
+ - [Git Branching - Branching Workflows](https://git-scm.com/book/en/v2/Git-Branching-Branching-Workflows)
+
+## Advanced use
+
+- [Custom Git Hooks](../../administration/custom_hooks.md)
+- [Git Attributes](../../user/project/git_attributes.md)
+- Git Submodules: [Using Git submodules with GitLab CI](../../ci/git_submodules.md#using-git-submodules-with-gitlab-ci)
+
+## API
+
+- [Gitignore templates](../../api/templates/gitignores.md)
+
+## Git LFS
+
+- [Git LFS](../../workflow/lfs/manage_large_binaries_with_git_lfs.md)
+- [Git-Annex to Git-LFS migration guide](https://docs.gitlab.com/ee/workflow/lfs/migrate_from_git_annex_to_git_lfs.html)
+- **Articles:**
+ - [Getting Started with Git LFS](https://about.gitlab.com/2017/01/30/getting-started-with-git-lfs-tutorial/)
+ - [Towards a production quality open source Git LFS server](https://about.gitlab.com/2015/08/13/towards-a-production-quality-open-source-git-lfs-server/)
+
+## General information
+
+- **Articles:**
+ - [The future of SaaS hosted Git repository pricing](https://about.gitlab.com/2016/05/11/git-repository-pricing/)
diff --git a/doc/topics/index.md b/doc/topics/index.md
new file mode 100644
index 00000000000..ad388dff822
--- /dev/null
+++ b/doc/topics/index.md
@@ -0,0 +1,16 @@
+# Topics
+
+Welcome to Topics! We have organized our content resources into topics
+to get you started on areas of your interest. Each topic page
+consists of an index listing all related content. It will guide
+you through better understanding GitLab's concepts
+through our regular docs, and, when available, through articles (guides,
+tutorials, technical overviews, blog posts) and videos.
+
+- [Authentication](authentication/index.md)
+- [Continuous Integration (GitLab CI)](../ci/README.md)
+- [Git](git/index.md)
+- [GitLab Installation](../install/README.md)
+- [GitLab Pages](../user/project/pages/index.md)
+
+>**Note:** More topics will be available soon.
diff --git a/doc/university/README.md b/doc/university/README.md
index 8b3538d5616..399d54bcf23 100644
--- a/doc/university/README.md
+++ b/doc/university/README.md
@@ -2,10 +2,10 @@
GitLab University is the best place to learn about **Version Control with Git and GitLab**.
-It doesn't replace, but accompanies our great [Documentation](http://docs.gitlab.com)
+It doesn't replace, but accompanies our great [Documentation](https://docs.gitlab.com)
and [Blog Articles](https://about.gitlab.com/blog/).
-Would you like to contribute to GitLab University? Then please take a look at our contribution [process](/process) for more information.
+Would you like to contribute to GitLab University? Then please take a look at our contribution [process](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/PROCESS.md) for more information.
## Gitlab University Curriculum
@@ -19,7 +19,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
---
-### 1. <a name="beginner"></a> GitLab Beginner
+### 1. GitLab Beginner
#### 1.1. Version Control and Git
@@ -31,7 +31,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [An Overview of GitLab.com - Video](https://www.youtube.com/watch?v=WaiL5DGEMR4)
1. [Why Use Git and GitLab - Slides](https://docs.google.com/a/gitlab.com/presentation/d/1RcZhFmn5VPvoFu6UMxhMOy7lAsToeBZRjLRn0LIdaNc/edit?usp=drive_web)
-1. [GitLab Basics - Article](http://doc.gitlab.com/ce/gitlab-basics/README.html)
+1. [GitLab Basics - Article](../gitlab-basics/README.md)
1. [Git and GitLab Basics - Video](https://www.youtube.com/watch?v=03wb9FvO4Ak&index=5&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
1. [Git and GitLab Basics - Online Course](https://courses.platzi.com/classes/git-gitlab/concepto/part-1/part-23370/material/)
1. [Comparison of GitLab Versions](https://about.gitlab.com/features/#compare)
@@ -51,10 +51,10 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
#### 1.5. Migrating from other Source Control
-1. [Migrating from BitBucket/Stash](http://doc.gitlab.com/ee/workflow/importing/import_projects_from_bitbucket.html)
-1. [Migrating from GitHub](http://doc.gitlab.com/ee/workflow/importing/import_projects_from_github.html)
-1. [Migrating from SVN](http://doc.gitlab.com/ee/workflow/importing/migrating_from_svn.html)
-1. [Migrating from Fogbugz](http://doc.gitlab.com/ee/workflow/importing/import_projects_from_fogbugz.html)
+1. [Migrating from BitBucket/Stash](https://docs.gitlab.com/ee/workflow/importing/import_projects_from_bitbucket.html)
+1. [Migrating from GitHub](https://docs.gitlab.com/ee/workflow/importing/import_projects_from_github.html)
+1. [Migrating from SVN](https://docs.gitlab.com/ee/workflow/importing/migrating_from_svn.html)
+1. [Migrating from Fogbugz](https://docs.gitlab.com/ee/workflow/importing/import_projects_from_fogbugz.html)
#### 1.6. GitLab Inc.
@@ -64,39 +64,41 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [Making GitLab Great for Everyone - Video](https://www.youtube.com/watch?v=GGC40y4vMx0) - Response to "Dear GitHub" letter
1. [Using Innersourcing to Improve Collaboration](https://about.gitlab.com/2014/09/05/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization/)
1. [The Software Development Market and GitLab - Video](https://www.youtube.com/watch?v=sXlhgPK1NTY&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e&index=6) - [Slides](https://docs.google.com/presentation/d/1vCU-NbZWz8NTNK8Vu3y4zGMAHb5DpC8PE5mHtw1PWfI/edit)
+1. [The GitLab Book Club](bookclub/index.md)
+1. [GitLab Resources](https://about.gitlab.com/resources/)
#### 1.7 Community and Support
-1. [Getting Help](/getting-help/)
+1. [Getting Help](https://about.gitlab.com/getting-help/)
- Proposing Features and Reporting and Tracking bugs for GitLab
- The GitLab IRC channel, Gitter Chat Room, Community Forum and Mailing List
- Getting Technical Support
- Being part of our Great Community and Contributing to GitLab
1. [Getting Started with the GitLab Development Kit (GDK)](https://about.gitlab.com/2016/06/08/getting-started-with-gitlab-development-kit/)
1. [Contributing Technical Articles to the GitLab Blog](https://about.gitlab.com/2016/01/26/call-for-writers/)
-1. [GitLab Training Workshops](/training)
+1. [GitLab Training Workshops](https://about.gitlab.com/training)
#### 1.8 GitLab Training Material
-1. [Git and GitLab Terminology](/glossary/)
+1. [Git and GitLab Terminology](glossary/README.md)
1. [Git and GitLab Workshop - Slides](https://docs.google.com/presentation/d/1JzTYD8ij9slejV2-TO-NzjCvlvj6mVn9BORePXNJoMI/edit?usp=drive_web)
1. [Git and GitLab Revision](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/university/training/end-user)
---
-### 2. <a name="intermediate"></a> GitLab Intermediate
+### 2. GitLab Intermediate
#### 2.1 GitLab Pages
1. [Using any Static Site Generator with GitLab Pages](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/)
1. [Securing GitLab Pages with SSL](https://about.gitlab.com/2016/06/24/secure-gitlab-pages-with-startssl/)
-1. [GitLab Pages Documentation](http://doc.gitlab.com/ee/pages/README.html)
+1. [GitLab Pages Documentation](https://docs.gitlab.com/ce/user/project/pages/)
#### 2.2. GitLab Issues
-1. [Markdown in GitLab](http://doc.gitlab.com/ce/markdown/markdown.html)
+1. [Markdown in GitLab](../user/markdown.md)
1. [Issues and Merge Requests - Video](https://www.youtube.com/watch?v=raXvuwet78M)
-1. [Due Dates and Milestones fro GitLab Issues](https://about.gitlab.com/2016/08/05/feature-highlight-set-dates-for-issues/)
+1. [Due Dates and Milestones for GitLab Issues](https://about.gitlab.com/2016/08/05/feature-highlight-set-dates-for-issues/)
1. [How to Use GitLab Labels](https://about.gitlab.com/2016/08/17/using-gitlab-labels/)
1. [Applying GitLab Labels Automatically](https://about.gitlab.com/2016/08/19/applying-gitlab-labels-automatically/)
1. [GitLab Issue Board - Product Page](https://about.gitlab.com/solutions/issueboard/)
@@ -128,7 +130,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [GitLab Flow vs Forking in GitLab - Video](https://www.youtube.com/watch?v=UGotqAUACZA)
1. [GitLab Flow Overview](https://about.gitlab.com/2014/09/29/gitlab-flow/)
1. [Always Start with an Issue](https://about.gitlab.com/2016/03/03/start-with-an-issue/)
-1. [GitLab Flow Documentation](http://doc.gitlab.com/ee/workflow/gitlab_flow.html)
+1. [GitLab Flow Documentation](https://docs.gitlab.com/ee/workflow/gitlab_flow.html)
#### 2.5. GitLab Comparisons
@@ -140,13 +142,13 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
---
-### 3. <a name="advanced"></a> GitLab Advanced
+### 3. GitLab Advanced
#### 3.1. Dev Ops
1. [Xebia Labs: Dev Ops Terminology](https://xebialabs.com/glossary/)
1. [Xebia Labs: Periodic Table of DevOps Tools](https://xebialabs.com/periodic-table-of-devops-tools/)
-1. [Puppet Labs: State of Dev Ops 2015 - Book](https://puppetlabs.com/sites/default/files/2015-state-of-devops-report.pdf)
+1. [Puppet Labs: State of Dev Ops 2016 - Book](https://puppet.com/resources/white-paper/2016-state-of-devops-report)
#### 3.2. Installing GitLab with Omnibus
@@ -164,7 +166,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
#### 3.4. Large Files
-1. [Big files in Git (Git LFS, Annex) - Video](https://www.youtube.com/watch?v=DawznUxYDe4)
+1. [Big files in Git (Git LFS) - Video](https://www.youtube.com/watch?v=DawznUxYDe4)
#### 3.5. LDAP and Active Directory
@@ -172,7 +174,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
#### 3.6 Custom Languages
-1. [How to add Syntax Highlighting Support for Custom Langauges to GitLab - Video](how to add support for your favorite language to GitLab)
+1. [How to add Syntax Highlighting Support for Custom Languages to GitLab - Video](https://youtu.be/6WxTMqatrrA)
#### 3.7. Scalability and High Availability
@@ -185,31 +187,34 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [GitLab Cycle Analytics Overview](https://about.gitlab.com/2016/09/21/cycle-analytics-feature-highlight/)
1. [GitLab Cycle Analytics - Product Page](https://about.gitlab.com/solutions/cycle-analytics/)
-#### 3.9. <a name="integrations"></a> Integrations
+#### 3.9. Integrations
1. [How to Integrate JIRA and Jenkins with GitLab - Video](https://gitlabmeetings.webex.com/gitlabmeetings/ldr.php?RCID=44b548147a67ab4d8a62274047146415)
-1. [How to Integrate Jira with GitLab](http://doc.gitlab.com/ee/integration/jira.html)
-1. [How to Integrate Jenkins with GitLab](http://doc.gitlab.com/ee/integration/jenkins.html)
-1. [How to Integrate Bamboo with GitLab](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/project_services/bamboo.md)
-1. [How to Integrate Slack with GitLab](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/slack.md)
+1. [How to Integrate Jira with GitLab](https://docs.gitlab.com/ce/user/project/integrations/jira.html)
+1. [How to Integrate Jenkins with GitLab](https://docs.gitlab.com/ee/integration/jenkins.html)
+1. [How to Integrate Bamboo with GitLab](https://docs.gitlab.com/ce/user/project/integrations/bamboo.html)
+1. [How to Integrate Slack with GitLab](https://docs.gitlab.com/ce/user/project/integrations/slack.html)
1. [How to Integrate Convox with GitLab](https://about.gitlab.com/2016/06/09/continuous-delivery-with-gitlab-and-convox/)
1. [Getting Started with GitLab and Shippable CI](https://about.gitlab.com/2016/05/05/getting-started-gitlab-and-shippable/)
---
-## 4. <a name="external"></a> External Articles
+### 4. External Articles
-1. [2011 WSJ article by Mark Andreeson - Software is Eating the World](http://www.wsj.com/articles/SB10001424053111903480904576512250915629460)
+1. [2011 WSJ article by Marc Andreessen - Software is Eating the World](http://www.wsj.com/articles/SB10001424053111903480904576512250915629460)
1. [2014 Blog post by Chris Dixon - Software eats software development](http://cdixon.org/2014/04/13/software-eats-software-development/)
1. [2015 Venture Beat article - Actually, Open Source is Eating the World](http://venturebeat.com/2015/12/06/its-actually-open-source-software-thats-eating-the-world/)
---
-## 5. <a name="team"></a> Resources for GitLab Team Members
+### 5. Resources for GitLab Team Members
*Some content can only be accessed by GitLab team members*
-1. [Support Path](/support/)
+1. [Support Path](support/README.md)
1. [Sales Path (redirect to sales handbook)](https://about.gitlab.com/handbook/sales-onboarding/)
+1. [User Training](training/user_training.md)
+1. [GitLab Flow Training](training/gitlab_flow.md)
+1. [Training Topics](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/university/training/topics/)
1. [GitLab architecture for noobs](https://dev.gitlab.org/gitlab/gitlabhq/blob/master/doc/development/architecture.md)
1. [Client Assessment of GitLab versus GitHub](https://docs.google.com/a/gitlab.com/spreadsheets/d/18cRF9Y5I6I7Z_ab6qhBEW55YpEMyU4PitZYjomVHM-M/edit?usp=sharing)
diff --git a/doc/university/bookclub/booklist.md b/doc/university/bookclub/booklist.md
new file mode 100644
index 00000000000..c4229832e9f
--- /dev/null
+++ b/doc/university/bookclub/booklist.md
@@ -0,0 +1,113 @@
+# Books
+
+List of books and resources, that may be worth reading.
+
+## Papers
+
+1. **The Humble Programmer**
+
+ Edsger W. Dijkstra, 1972 ([paper](http://dl.acm.org/citation.cfm?id=361591))
+
+## Programming
+
+1. **Design Patterns: Elements of Reusable Object-Oriented Software**
+
+ Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, 1994 ([amazon](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612))
+
+1. **Clean Code: A Handbook of Agile Software Craftsmanship**
+
+ Robert C. "Uncle Bob" Martin, 2008 ([amazon](http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882))
+
+1. **Code Complete: A Practical Handbook of Software Construction**, 2nd Edition
+
+ Steve McConnell, 2004 ([amazon](http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670))
+
+1. **The Pragmatic Programmer: From Journeyman to Master**
+
+ Andrew Hunt, David Thomas, 1999 ([amazon](http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X))
+
+1. **Working Effectively with Legacy Code**
+
+ Michael Feathers, 2004 ([amazon](http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052))
+
+1. **Eloquent Ruby**
+
+ Russ Olsen, 2011 ([amazon](http://www.amazon.com/Eloquent-Ruby-Addison-Wesley-Professional/dp/0321584104))
+
+1. **Domain-Driven Design: Tackling Complexity in the Heart of Software**
+
+ Eric Evans, 2003 ([amazon](http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215))
+
+1. **How to Solve It: A New Aspect of Mathematical Method**
+
+ Polya G. 1957 ([amazon](http://www.amazon.com/How-Solve-Mathematical-Princeton-Science/dp/069116407X))
+
+1. **Software Creativity 2.0**
+
+ Robert L. Glass, 2006 ([amazon](http://www.amazon.com/Software-Creativity-2-0-Robert-Glass/dp/0977213315))
+
+1. **Object-Oriented Software Construction**
+
+ Bertrand Meyer, 1997 ([amazon](http://www.amazon.com/Object-Oriented-Software-Construction-Book-CD-ROM/dp/0136291554))
+
+1. **Refactoring: Improving the Design of Existing Code**
+
+ Martin Fowler, Kent Beck, 1999 ([amazon](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672))
+
+1. **Test Driven Development: By Example**
+
+ Kent Beck, 2002 ([amazon](http://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530))
+
+1. **Algorithms in C++: Fundamentals, Data Structure, Sorting, Searching**
+
+ Robert Sedgewick, 1990 ([amazon](http://www.amazon.com/Algorithms-Parts-1-4-Fundamentals-Structure/dp/0201350882))
+
+1. **Effective C++**
+
+ Scott Mayers, 1996 ([amazon](http://www.amazon.com/Effective-Specific-Improve-Programs-Designs/dp/0321334876))
+
+1. **Extreme Programming Explained: Embrace Change**
+
+ Kent Beck, 1999 ([amazon](http://www.amazon.com/Extreme-Programming-Explained-Embrace-Change/dp/0321278658))
+
+1. **The Art of Computer Programming**
+
+ Donald E. Knuth, 1997 ([amazon](http://www.amazon.com/Computer-Programming-Volumes-1-4A-Boxed/dp/0321751043))
+
+1. **Writing Efficient Programs**
+
+ Jon Louis Bentley, 1982 ([amazon](http://www.amazon.com/Writing-Efficient-Programs-Prentice-Hall-Software/dp/013970244X))
+
+1. **The Mythical Man-Month: Essays on Software Engineering**
+
+ Frederick Phillips Brooks, 1975 ([amazon](http://www.amazon.com/Mythical-Man-Month-Essays-Software-Engineering/dp/0201006502))
+
+1. **Peopleware: Productive Projects and Teams** 3rd Edition
+
+ Tom DeMarco, Tim Lister, 2013 ([amazon](http://www.amazon.com/Peopleware-Productive-Projects-Teams-3rd/dp/0321934113))
+
+1. **Principles Of Software Engineering Management**
+
+ Tom Gilb, 1988 ([amazon](http://www.amazon.com/Principles-Software-Engineering-Management-Gilb/dp/0201192462))
+
+## Other
+
+1. **Thinking, Fast and Slow**
+
+ Daniel Kahneman, 2013 ([amazon](http://www.amazon.com/Thinking-Fast-Slow-Daniel-Kahneman/dp/0374533555))
+
+1. **The Social Animal** 11th Edition
+
+ Elliot Aronson, 2011 ([amazon](http://www.amazon.com/Social-Animal-Elliot-Aronson/dp/1429233419))
+
+1. **Influence: Science and Practice** 5th Edition
+
+ Robert B. Cialdini, 2008 ([amazon](http://www.amazon.com/Influence-Practice-Robert-B-Cialdini/dp/0205609996))
+
+1. **Getting to Yes: Negotiating Agreement Without Giving In**
+
+ Roger Fisher, William L. Ury, Bruce Patton, 2011 ([amazon](http://www.amazon.com/Getting-Yes-Negotiating-Agreement-Without/dp/0143118757))
+
+1. **How to Win Friends & Influence People**
+
+ Dale Carnegie, 1981 ([amazon](http://www.amazon.com/How-Win-Friends-Influence-People/dp/0671027034))
diff --git a/doc/university/bookclub/index.md b/doc/university/bookclub/index.md
new file mode 100644
index 00000000000..022a61f4429
--- /dev/null
+++ b/doc/university/bookclub/index.md
@@ -0,0 +1,19 @@
+# The GitLab Book Club
+
+The Book Club is a casual meet-up to read and discuss books we like.
+We'll find a time that suits most, if not all.
+
+See the [book list](booklist.md) for additional recommendations.
+
+## Currently reading : Books about remote work
+
+1. **Remote: Office not required**
+
+ David Heinemeier Hansson and Jason Fried, 2013
+ ([amazon](http://www.amazon.co.uk/Remote-Required-David-Heinemeier-Hansson/dp/0091954673))
+
+1. **The Year Without Pants**
+
+ Scott Berkun, 2013 ([ScottBerkun.com](http://scottberkun.com/yearwithoutpants/))
+
+Any other books you'd like to suggest? Edit this page and add them to the queue.
diff --git a/doc/university/glossary/README.md b/doc/university/glossary/README.md
index a86ff165f2e..9544de41b9a 100644
--- a/doc/university/glossary/README.md
+++ b/doc/university/glossary/README.md
@@ -1,4 +1,3 @@
-
## What is the Glossary
This contains a simplified list and definitions of some of the terms that you will encounter in your day to day activities when working with GitLab.
@@ -6,83 +5,87 @@ Please add any terms that you discover that you think would be useful for others
### 2FA
-User authentication by combination of 2 different steps during login. This allows for more security.
+User authentication by combination of 2 different steps during login. This allows for [more security](https://about.gitlab.com/handbook/security/).
### Access Levels
-Process of selective restriction to create, view, modify or delete a resource based on a set of assigned permissions.
-See, [GitLab's Permission Guidelines](http://doc.gitlab.com/ce/permissions/permissions.html)
+Process of selective restriction to create, view, modify or delete a resource based on a set of assigned permissions. See [GitLab's Permission Guidelines](../../user/permissions.md)
### Active Directory (AD)
-A Microsoft based directory service for windows domain networks. It uses LDAP technology under the hood
+A Microsoft-based [directory service](https://msdn.microsoft.com/en-us/library/bb742424.aspx) for windows domain networks. It uses LDAP technology under the hood.
### Agile
-Building and delivering software in phases/parts rather than trying to build everything at once then delivering to the user/client. The later is known as a WaterFall model
+Building and [delivering software](http://agilemethodology.org/) in phases/parts rather than trying to build everything at once then delivering to the user/client. The latter is known as the WaterFall model.
### Application Lifecycle Management (ALM)
-Entire product lifecycle management process for an application. From requirements management, development and testing until deployment.
+The entire product lifecycle management process for an application, from requirements management, development, and testing until deployment. GitLab has [advantages](https://docs.google.com/presentation/d/1vCU-NbZWz8NTNK8Vu3y4zGMAHb5DpC8PE5mHtw1PWfI/edit#slide=id.g72f2e4906_2_288) over both legacy and modern ALM tools.
### Artifactory
-Version control for binaries.
+A version control [system](https://www.jfrog.com/open-source/#os-arti) for non-text files.
### Artifacts
-objects (usually binary and large) created by a build process
+Objects (usually binary and large) created by a build process. These can include use cases, class diagrams, requirements and design documents.
### Atlassian
-A company that develops software products for developers and project managers including Bitbucket, Jira, Hipchat, Confluence, Bamboo. See [Atlassian] (https://www.atlassian.com)
+A [company](https://www.atlassian.com) that develops software products for developers and project managers including Bitbucket, Jira, Hipchat, Confluence, Bamboo.
### Audit Log
-*** Needs definition here
+Also called an [audit trail](https://en.wikipedia.org/wiki/Audit_trail), an audit log is a document that records an event in an IT system.
### Auto Defined User Group
-User groups are a way of centralizing control over important management tasks, particularly access control and password policies.
-A simple example of such groups are the users and the admins groups.
-In most of the cases these groups are auto defined in terms of access, rules of usage, conditions to be part of, etc...
+User groups are a way of centralizing control over important management tasks, particularly access control and password policies. A simple example of such groups are the users and the admins groups.
+In most of the cases these groups are auto defined in terms of access, rules of usage, conditions to be part of, etc.
### Bamboo
-Atlassian's CI tool similar to GitLab CI and Jenkins
+Atlassian's CI tool similar to GitLab CI and Jenkins.
### Basic Subscription
-Entry level subscription for GitLab EE currently available in packs of 10 see [Basic subscription](https://about.gitlab.com/pricing/)
+Entry level [subscription](https://about.gitlab.com/pricing/) for GitLab EE currently available in packs of 10.
### Bitbucket
-Atlassian's web hosting service for Git and Mercurial Projects i.e. GitLab.com competitor
+Atlassian's web hosting service for Git and Mercurial Projects. Read about [migrating](https://docs.gitlab.com/ce/workflow/importing/import_projects_from_bitbucket.html) from BitBucket to a GitLab instance.
### Branch
-A branch is a parallel version of a repository. Allows you to work on the repository without you affecting the "master" branch. Allows you to make changes without affecting the current "live" version. When you have made all your changes to your branch you can then merge to the master and to make the changes fo "live".
+A branch is a parallel version of a repository. This allows you to work on the repository without affecting the "master" branch, and without affecting the current "live" version. When you have made all your changes to your branch you can then merge to the master. When your merge request is accepted your changes will be "live."
### Branded Login
-Having your own logo on your GitLab instance login page instead of the GitLab logo.
+Having your own logo on [your GitLab instance login page](https://docs.gitlab.com/ee/customization/branded_login_page.html) instead of the GitLab logo.
+
+### Job triggers
+These protect your code base against breaks, for instance when a team is working on the same project. Learn about [setting up](https://docs.gitlab.com/ce/ci/triggers/README.html) job triggers.
### CEPH
-is a distributed object store and file system designed to provide excellent performance, reliability and scalability.
+ A distributed object store and file [system](http://ceph.com/) designed to provide excellent performance, reliability and scalability.
+
+### ChatOps
+
+The ability to [initiate an action](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/1412) from chat. ChatBots run in your chat application and give you the ability to do "anything" from chat.
### Clone
-A copy of a repository stored on your machine that allows you to use your own editor without being online, but still tracks the changes made remotely.
+A [copy](https://git-scm.com/docs/git-clone) of a repository stored on your machine that allows you to use your own editor without being online, but still tracks the changes made remotely.
### Code Review
-Examination of a progam's code. The main aim is to maintain high standards quality of code that is being shipped.
+Examination of a progam's code. The main aim is to maintain high quality standards of code that is being shipped. Merge requests [serve as a code review tool](https://about.gitlab.com/2014/09/29/gitlab-flow/) in GitLab.
### Code Snippet
-A small amount of code. Usually for the purpose of showing other developers how
-to do something specific or reproduce a problem.
+A small amount of code, usually selected for the purpose of showing other developers how to do something specific or reproduce a problem.
### Collaborator
@@ -90,31 +93,39 @@ Person with read and write access to a repository who has been invited by reposi
### Commit
-Is a change (revision) to a file, and also creates an ID that allows you to see revision history and who made the changes.
+A [change](https://git-scm.com/docs/git-commit) (revision) to a file that also creates an ID, allowing you to see revision history and the author of the changes.
### Community
-Everyone who is using GitLab
+[Everyone](https://about.gitlab.com/community/) who uses GitLab.
### Confluence
-Atlassian's product for collaboration of documents and projects.
+Atlassian's product for collaboration on documents and projects.
-### Continuous Deivery
+### Continuous Delivery
-Continuous delivery is a series of practices designed to ensure that code can be rapidly and safely deployed to production by delivering every change to a production-like environment and ensuring business applications and services function as expected through rigorous automated testing.
+A [software engineering approach](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) in which continuous integration, automated testing, and automated deployment capabilities allow software to be developed and deployed rapidly, reliably and repeatedly with minimal human intervention. Still, the deployment to production is defined strategically and triggered manually.
### Continuous Deployment
-Continuous deployment is the next step of continuous delivery: Every change that passes the automated tests is deployed to production automatically.
+A [software development practice](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) in which every code change goes through the entire pipeline and is put into production automatically, resulting in many production deployments every day. It does everything that Continuous Delivery does, but the process is fully automated, there's no human intervention at all.
### Continuous Integration
-A process that involves adding new code commits to source code with the combined code being run on an automated test to ensure that the changes do not break the software.
+A [software development practice](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) in which you build and test software every time a developer pushes code to the application, and it happens several times a day.
### Contributor
-Term used to a person contributing to an Open Source Project.
+Term used for a person contributing to an open source project.
+
+### Conversational Development (ConvDev)
+
+A [natural evolution](https://about.gitlab.com/2016/09/14/gitlab-live-event-recap/) of software development that carries a conversation across functional groups throughout the development process, enabling developers to track the full path of development in a cohesive and intuitive way. ConvDev accelerates the development lifecycle by fostering collaboration and knowledge sharing from idea to production.
+
+### Cycle Time
+
+The time it takes to move from [idea to production](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab).
### Data Centre
@@ -122,41 +133,59 @@ Atlassian product for High Availability.
### Deploy Keys
-An SSH key stored on the your server that grants access to a single GitLab repository. This is used by a GitLab runner to clone a project's code so that tests can be run against the checked out code.
+A [SSH key](https://docs.gitlab.com/ce/gitlab-basics/create-your-ssh-keys.html)stored on your server that grants access to a single GitLab repository. This is used by a GitLab runner to clone a project's code so that tests can be run against the checked out code.
### Developer
-For us (GitLab) this means a software developer, i.e. someone who makes software. It is also one of the levels of access in our multi level approval system.
+For us at GitLab, this means a software developer, or someone who makes software. It is also one of the levels of access in our multi-level approval system.
+
+### DevOps
+
+The intersection of software engineering, quality assurance, and technology operations. Explore more DevOps topics in the [glossary by XebiaLabs](https://xebialabs.com/glossary/)
### Diff
-Is the difference between two commits, or saved changes. This will also be shown visually after the changes.
+The difference between two commits, or saved changes. This will also be shown visually after the changes.
+
+#### Directory
+
+A folder used for storing multiple files.
+
+### Docker Container Registry
+
+A [feature](https://docs.gitlab.com/ce/user/project/container_registry.html) of GitLab projects. Containers wrap up a piece of software in a complete filesystem that contains everything it needs to run: code, runtime, system tools, system libraries – anything you can install on a server. This guarantees that it will always run the same, regardless of the environment it is running in.
-### Docker
+### Dynamic Environment
-Containers wrap up a piece of software in a complete filesystem that contains everything it needs to run: code, runtime, system tools, system libraries – anything you can install on a server.
-This guarantees that it will always run the same, regardless of the environment it is running in.
+### ElasticSearch
+
+Elasticsearch is a flexible, scalable and powerful search service. When [enabled](https://gitlab.com/help/integration/elasticsearch.md), it helps keep GitLab's search fast when dealing with a huge amount of data.
+
+### Emacs
### Fork
-Your own copy of a repository that allows you to make changes to the repository without affecting the original.
+Your [own copy](https://docs.gitlab.com/ce/workflow/forking_workflow.html) of a repository that allows you to make changes to the repository without affecting the original.
### Gerrit
-A code review tool built on top of Git.
+A code review [tool](https://www.gerritcodereview.com/) built on top of Git.
+
+### Git Attributes
+
+A [git attributes file](https://git-scm.com/docs/gitattributes) is a simple text file that gives attributes to pathnames.
### Git Hooks
-Are scripts you can use to trigger actions at certain points.
+[Scripts](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) you can use to trigger actions at certain points.
### GitHost.io
-Is a single-tenant solution that provides GitLab CE or EE as a managed service. GitLab Inc. is responsible for
-installing, updating, hosting, and backing up customers own private and secure GitLab instance.
+A single-tenant solution that provides GitLab CE or EE as a managed service. GitLab Inc. is responsible for installing, updating, hosting, and backing up customers' own private and secure GitLab instance.
### GitHub
-A web-based Git repository hosting service with an enterprise offering. Its main features are: issue tracking, pull request with code review, abundancy of integrations and wiki. As of April 2016, the service has over 14 million users. It offers free public repos, private repos and enterprise services are paid.
+A web-based Git repository hosting service with an enterprise offering. Its main features are: issue tracking, pull request with code review, abundancy of integrations and wiki. It offers free public repos, private repos and enterprise services are paid. Read about [importing a project](https://docs.gitlab.com/ce/workflow/importing/import_projects_from_github.html) from GitHub to GitLab.
### GitLab CE
@@ -164,51 +193,78 @@ Our free on Premise solution with >100,000 users
### GitLab CI
-Our own Continuos Integration feature that is shipped with each instance
+Our own Continuos Integration [feature](https://about.gitlab.com/gitlab-ci/) that is shipped with each instance
### GitLab EE
-Our premium on premise solution that currently has Basic, Standard and Plus subscription packages with additional features and support.
+Our premium on premise [solution](https://about.gitlab.com/features/#enterprise) that currently has Basic, Standard and Plus subscription packages with additional features and support.
### GitLab.com
Our free SaaS for public and private repositories.
+### GitLab Geo
+
+Allows you to replicate your GitLab instance to other geographical locations as a read-only fully operational version. It [can be used](https://docs.gitlab.com/ee/gitlab-geo/README.html) for cloning and fetching projects, in addition to reading any data. This will make working with large repositories over large distances much faster.
+
+### GitLab Pages
+These allow you to [create websites](https://gitlab.com/help/pages/README.md) for your GitLab projects, groups, or user account.
+
### Gitolite
-Is basically an access layer that sits on top of Git. Users are granted access to repos via a simple config file and you as an admin only needs the users public SSH key and a username from the user.
+An [access layer](https://git-scm.com/book/en/v1/Git-on-the-Server-Gitolite) that sits on top of Git. Users are granted access to repos via a simple config file. As an admin, you only need the users' public SSH key and a username.
### Gitorious
-A web based hosting service for projects using Git. It was acquired by GitLab and we discontinued the service. [Gitorious Acquisition Blog Post](https://about.gitlab.com/2015/03/03/gitlab-acquires-gitorious/)
+A web-based hosting service for projects using Git. It was acquired by GitLab and we discontinued the service. Read the[Gitorious Acquisition Blog Post](https://about.gitlab.com/2015/03/03/gitlab-acquires-gitorious/).
+
+### Go
+
+An open source programming [language](https://golang.org/).
-### HADR
+### GUI/ Git GUI
-Sometimes written HA/DR. High Availability for Disaster Recovery. Usually refers to a strategy having a failover server in place in case the main server fails.
+A portable [graphical interface](https://git-scm.com/docs/git-gui) to Git that allows users to make changes to their repository by making new commits, amending existing ones, creating branches, performing local merges, and fetching/pushing to remote repositories.
+
+### High Availability for Disaster Recovery (HADR)
+
+Sometimes written HA/DR, this usually refers to a strategy for having a failover server in place in case the main server fails.
### Hip Chat
-Atlassian's real time chat application for teams. Competitor to Slack, RocketChat and MatterMost.
+Atlassian's real time chat application for teams, Hip Chat is a competitor to Slack, RocketChat and MatterMost.
### High Availability
-Refers to a system or component that is continuously operational for a desirably long length of time. Availability can be measured relative to "100% operational" or "never failing."
+Refers to a [system or component](https://about.gitlab.com/high-availability/) that is continuously operational for a desirably long length of time. Availability can be measured relative to "100% operational" or "never failing."
+
+### Inner-sourcing
+
+The [use of](https://about.gitlab.com/2014/09/05/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization/) open source development techniques within the corporation.
+
+### Internet Relay Chat (IRC)
+
+An [application layer protocol](http://www.irchelp.org/) that facilitates communication in the form of text.
### Issue Tracker
-A tool used to manage, organize, and maintain a list of issues, making it easier for an organization to manage.
+A [tool](https://docs.gitlab.com/ee/integration/external-issue-tracker.html) used to manage, organize, and maintain a list of issues, making it easier for an organization to manage.
### Jenkins
-An Open Source CI tool written using the Java programming language. Does the same job as GitLab CI, Bamboo, Travis CI. It is extremely popular. see [Jenkins](https://jenkins-ci.org/)
+An Open Source CI tool written using the Java programming language. [Jenkins](https://jenkins-ci.org/) does the same job as GitLab CI, Bamboo, and Travis CI. It is extremely popular.
### Jira
-Atlassian's project management software. i.e. a complex issue tracker. See[Jira](https://www.atlassian.com/software/jira)
+Atlassian's [project management software](https://www.atlassian.com/software/jira), i.e. a complex issue tracker. GitLab [can be configured](https://docs.gitlab.com/ee/project_services/jira.html) to interact with JIRA Core either using an on-premise instance or the SaaS solution that Atlassian offers.
+
+### JUnit
+
+A testing framework for the Java programming language, [JUnit](http://junit.org/junit4/) has been important in the evolution of test-driven development.
### Kerberos
-A network authentication protocol that uses secret-key cryptography for security.
+A network authentication [protocol](http://web.mit.edu/kerberos/) that uses secret-key cryptography for security.
### Kubernetes
@@ -216,23 +272,27 @@ An open source container cluster manager originally designed by Google. It's bas
### Labels
-An identifier to describe a group of one or more specific file revisions
+An [identifier](https://docs.gitlab.com/ce/user/project/labels.html) to describe a group of one or more specific file revisions.
-### LDAP
+### Lightweight Directory Access Protocol (LDAP)
-Lightweight Directory Access Protocol - basically its a directory (electronic address book) with user information e.g. name, phone_number etc
+ A directory (electronic address book) with user information (e.g. name, phone_number etc.)
### LDAP User Authentication
-Allowing GitLab to sign in people from an LDAP server i.e. Allow people whose names are on the electronic user directory server) to be able to use their LDAP accounts to login.
+GitLab [integrates](https://docs.gitlab.com/ce/administration/auth/ldap.html) with LDAP to support user authentication. This enables GitLab to sign in people from an LDAP server (i.e., allowing people whose names are on the electronic user directory server to be able to use their LDAP accounts to login.)
### LDAP Group Sync
Allows you to synchronize the members of a GitLab group with one or more LDAP groups.
-### Git LFS
+### Load Balancer
+
+A [device](https://en.wikipedia.org/wiki/Load_balancing_(computing)) that distributes network or application traffic across multiple servers.
-Git Large File Storage. A way to enable git to handle large binary files by using reference pointers within small text files to point to the large files.
+### Git Large File Storage (LFS)
+
+A way [to enable](https://about.gitlab.com/2015/11/23/announcing-git-lfs-support-in-gitlab/) git to handle large binary files by using reference pointers within small text files to point to the large files. Large files such as high resolution images and videos, audio files, and assets can be called from a remote server.
### Linux
@@ -240,8 +300,7 @@ An operating system like Windows or OS X. It is mostly used by software develope
### Markdown
-Is a lightweight markup language with plain text formatting syntax designed so that it can be converted to HTML and many other formats using a tool by the same name.
-Markdown is often used to format readme files, for writing messages in online discussion forums, and to create rich text using a plain text editor.
+A lightweight markup language with plain text formatting syntax designed so that it can be converted to HTML and many other formats using a tool by the same name. Markdown is often used to format readme files, for writing messages in online discussion forums, and to create rich text using a plain text editor. Checkout GitLab's [Markdown guide](https://gitlab.com/help/user/markdown.md).
### Maria DB
@@ -249,193 +308,219 @@ A community developed fork/variation of MySQL. MySQL is owned by Oracle.
### Master
-Name of the default branch in every git repository.
+Name of the [default branch](https://git-scm.com/book/en/v1/Git-Branching-What-a-Branch-Is) in every git repository.
+
+### Mattermost
+
+An open source, self-hosted messaging alternative to Slack. View GitLab's Mattermost [feature](https://gitlab.com/gitlab-org/gitlab-mattermost).
### Mercurial
-A free distributed version control system like Git. Think of it as a competitor to Git.
+A free distributed version control system similar to and a competitor with Git.
### Merge
-Takes changes from one branch, and applies them into another branch.
+Takes changes from one branch, and [applies them](https://git-scm.com/docs/git-merge) into another branch.
+
+### Merge Conflict
+
+[Arises](https://about.gitlab.com/2016/09/06/resolving-merge-conflicts-from-the-gitlab-ui/) when a merge can't be performed cleanly between two versions of the same file.
### Meteor
-A hip platform for building javascript apps.[Meteor] (https://www.meteor.com)
+A [platform](https://www.meteor.com) for building javascript apps.
### Milestones
-Allows you to track the progress on issues, and merge requests, which allows you to get a snapshot of the progress made.
+Allow you to [organize issues](../../user/project/milestones/index.md) and merge requests in GitLab into a cohesive group, optionally setting a due date. A common use is keeping track of an upcoming software version. Milestones are created per-project.
### Mirror Repositories
-You can set up a project to automatically have its branches, tags, and commits updated from an upstream repository. This is useful when a repository you're interested in is located on a different server, and you want to be able to browse its content and its activity using the familiar GitLab interface.
+A project that is setup to automatically have its branches, tags, and commits [updated from an upstream repository](https://docs.gitlab.com/ee/workflow/repository_mirroring.html). This is useful when a repository you're interested in is located on a different server, and you want to be able to browse its content and activity using the familiar GitLab interface.
### MIT License
-A type of software license. It lets people do anything with your code with proper attribution and without warranty. It is the most common license for open source applications written in Ruby on Rails. GitLab CE is issued under this license.
-This means, you can download the code, modify it as you want even build a new commercial product using the underlying code and its not illegal. The only condition is that there is no form of waranty provided by GitLab so whatever happens if you use the code is your own problem.
-
-### Mondo
-
-*** Needs definition here
+A type of software license. It lets people do anything with your code with proper attribution and without warranty. It is the most common license for open source applications written in Ruby on Rails. GitLab CE is issued under this [license](https://docs.gitlab.com/ce/development/licensing.html). This means you can download the code, modify it as you want, and even build a new commercial product using the underlying code and it's not illegal. The only condition is that there is no form of warranty provided by GitLab so whatever happens when you use the code is your own problem.
-### Multi LDAP Server
+### Mondo Rescue
-*** Needs definition here
+A free disaster recovery [software](https://help.ubuntu.com/community/MondoMindi).
-### My SQL
+### MySQL
-A relational database. Currently only supported if you are using EE. It is owned by Oracle.
+A relational [database](http://www.mysql.com/) owned by Oracle. Currently only supported if you are using EE.
### Namespace
-In computing, a namespace is a set of symbols that are used to organize objects of various kinds, so that these objects may be referred to by name.
-
-Prominent examples include:
-- file systems are namespaces that assign names to files;
-- programming languages organize their variables and subroutines in namespaces;
-- computer networks and distributed systems assign names to resources, such as computers, printers, websites, (remote) files, etc.
+A set of symbols that are used to organize objects of various kinds so that these objects may be referred to by name. Examples of namespaces in action include file systems that assign names to files; programming languages that organize their variables and subroutines in namespaces; and computer networks and distributed systems that assign names to resources, such as computers, printers, websites, (remote) files, etc.
### Nginx
-(pronounced "engine x") is a web server. It can act as a reverse proxy server for HTTP, HTTPS, SMTP, POP3, and IMAP protocols, as well as a load balancer and an HTTP cache.
+A web [server](https://www.nginx.com/resources/wiki/) (pronounced "engine x"). It can act as a reverse proxy server for HTTP, HTTPS, SMTP, POP3, and IMAP protocols, as well as a load balancer and an HTTP cache.
-### oAuth
+### OAuth
-Is an open standard for authorization, commonly used as a way for Internet users to log into third party websites using their Microsoft, Google, Facebook or Twitter accounts without exposing their password.
+An open standard for authorization, commonly used as a way for internet users to log into third party websites using their Microsoft, Google, Facebook or Twitter accounts without exposing their password. GitLab [is](https://docs.gitlab.com/ce/integration/oauth_provider.html) an OAuth2 authentication service provider.
### Omnibus Packages
-Omnibus is a way to package the different services and tools required to run GitLab, so that users can install it without as much work.
+A way to [package different services and tools](https://docs.gitlab.com/omnibus/) required to run GitLab, so that most developers can install it without laborious configuration.
### On Premise
-On your own server. In GitLab, this refers to the ability to download GitLab EE/GitLab CE and host it on your own server rather than using GitLab.com which is hosted by GitLab Inc's servers.
+On your own server. In GitLab, this [refers](https://about.gitlab.com/2015/02/12/why-ship-on-premises-in-the-saas-era/) to the ability to download GitLab EE/GitLab CE and host it on your own server rather than using GitLab.com, which is hosted by GitLab Inc's servers.
+
+### Open Core
+
+GitLab's [business model](https://about.gitlab.com/2016/07/20/gitlab-is-open-core-github-is-closed-source/). Coined by Andrew Lampitt in 2008, the [open core model](https://en.wikipedia.org/wiki/Open_core) primarily involves offering a "core" or feature-limited version of a software product as free and open-source software, while offering "commercial" versions or add-ons as proprietary software.
### Open Source Software
-Software for which the original source code is freely available and may be redistributed and modified.
+Software for which the original source code is freely [available](https://opensource.org/docs/osd) and may be redistributed and modified. GitLab prioritizes open source [stewardship](https://about.gitlab.com/2016/01/11/being-a-good-open-source-steward/).
### Owner
-This is the most powerful person on a GitLab project. He has the permissions of all the other users plus the additional permission of being able to destroy i.e. delete the project
+The most powerful person on a GitLab project. They have the permissions of all the other users plus the additional permission of being able to destroy (i.e. delete) the project.
-### PaaS
+### Platform as a Service (PaaS)
-Typically referred to in regards to application development, it is a model in which a cloud provider delivers hardware and software tools to its users as a service
+Typically referred to in regards to application development, PaaS is a model in which a cloud provider delivers hardware and software tools to its users as a service.
### Perforce
-The company that produces Helix. A commercial, proprietary, centralised VCS well known for it's ability to version files of any size and type. They OEM a re-branded version of GitLab called "GitSwarm" that is tightly integrated with their "GitFusion" product, which in turn represents a portion of a Helix repository (called a depot) as a git repo
+The company that produces Helix. A commercial, proprietary, centralised VCS well known for its ability to version files of any size and type. They OEM a re-branded version of GitLab called "GitSwarm" that is tightly integrated with their "GitFusion" product, which in turn represents a portion of a Helix repository (called a depot) as a git repo.
### Phabricator
-Is a suite of web-based software development collaboration tools, including the Differential code review tool, the Diffusion repository browser, the Herald change monitoring tool, the Maniphest bug tracker and the Phriction wiki. Phabricator integrates with Git, Mercurial, and Subversion.
+A suite of web-based software development collaboration tools, including the Differential code review tool, the Diffusion repository browser, the Herald change monitoring tool, the Maniphest bug tracker and the Phriction wiki. Phabricator integrates with Git, Mercurial, and Subversion.
### Piwik Analytics
-An open source analytics software to help you analyze web traffic. It is similar to google analytics only that google analytics is not open source and information is stored by google while in Piwik the information is stored in your own server hence fully private.
+An open source analytics software to help you analyze web traffic. It is similar to Google Analytics, except that the latter is not open source and information is stored by Google. In Piwik, the information is stored on your own server and hence is fully private.
### Plus Subscription
-GitLab Premium EE subscription that includes training and dedicated Account Management and Service Engineer and complete support package [Plus subscription](https://about.gitlab.com/pricing/)
+GitLab Premium EE [subscription](https://about.gitlab.com/pricing/) that includes training and dedicated Account Management and Service Engineer and complete support package.
### PostgreSQL
-A relational database. Touted as the most advanced open source database.
+An [object-relational](https://en.wikipedia.org/wiki/PostgreSQL) database. Touted as the most advanced open source database, it is one of two database management systems [supported by](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/database.md) GitLab, the other being MySQL.
### Protected Branches
-A feature that protects branches from unauthorized pushes, force pushing or deletion.
+A [feature](https://docs.gitlab.com/ce/user/project/protected_branches.html) that protects branches from unauthorized pushes, force pushing or deletion.
+
+### Protected Tags
+
+A [feature](https://docs.gitlab.com/ce/user/project/protected_tags.html) that protects tags from unauthorized creation, update or deletion
### Pull
-Git command to synchronize the local repository with the remote repository, by fetching all remote changes and merging them into the local repository.
+Git command to [synchronize](https://git-scm.com/docs/git-pull) the local repository with the remote repository, by fetching all remote changes and merging them into the local repository.
### Puppet
-A popular devops automation tool
+A popular DevOps [automation tool](https://puppet.com/product/how-puppet-works).
### Push
-Git command to send commits from the local repository to the remote repository.
+Git [command](https://git-scm.com/docs/git-push) to send commits from the local repository to the remote repository. Read about [advanced push rules](https://gitlab.com/help/pages/README.md) in GitLab.
### RE Read Only
-Permissions to see a file and it's contents, but not change it
+Permissions to see a file and its contents, but not change it.
### Rebase
-Moves a branch from one commit to another. This allows you to re-write your project's history.
+In addition to the merge, the [rebase](https://git-scm.com/book/en/v2/Git-Branching-Rebasing) is a main way to integrate changes from one branch into another.
-### Git Repository
+### (Git) Repository
-Storage location of all files which are tracked by git.
+A directory where Git [has been initiatlized](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository) to start version controlling your files. The history of your work is stored here. A remote repository is not on your machine, but usually online (like on GitLab.com, for instance). The main remote repository is usually called "Origin."
### Requirements management
-*** Needs definition here
-
-### Revision
-
-*** Needs definition here
+Gives your distributed teams a single shared repository to collaborate and share requirements, understand their relationship to tests, and evaluate linked defects. It includes multiple, preconfigured requirement types.
### Revision Control
-Also known as version control or source control, is the management of changes to documents, computer programs, large web sites, and other collections of information. Changes are usually identified by a number or letter code, termed the "revision number", "revision level", or simply "revision".
+Also known as version control or source control, this is the management of changes to documents, computer programs, large web sites, and other collections of information. Changes are usually identified by a number or letter code, termed the "revision number," "revision level," or simply "revision."
### RocketChat
-An open source chat application for teams. Very similar to Slack only that is is open-source.
+An open source chat application for teams, RocketChat is very similar to Slack but it is also open-source.
+
+### Route Table
+
+A route table contains rules (called routes) that determine where network traffic is directed. Each [subnet in a VPC](http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) must be associated with a route table.
### Runners
-Actual build machines/containers that run/execute tests you have specified to be run on GitLab CI
+Actual build machines/containers that [run and execute tests](https://gitlab.com/gitlab-org/gitlab-ci-multi-runner) you have specified to be run on GitLab CI.
+
+### Sidekiq
+
+The background job processor GitLab [uses](https://docs.gitlab.com/ce/administration/troubleshooting/sidekiq.html) to asynchronously run tasks.
-### SaaS
+### Software as a service (SaaS)
-Software as a service. Software is hosted centrally and accessed on-demand i.e. when you want to. This refers to GitLab.com in our scenario
+Software that is hosted centrally and accessed on-demand (i.e. whenever you want to). This applies to GitLab.com.
-### SCM
+### Software Configuration Management (SCM)
-Software Configuration Management. Often used by people when they mean Version Control
+This term is often used by people when they mean "Version Control."
## Scrum
-An Agile framework designed to help complete complex (typically) software projects. It's made up of several parts: product requirments backlog, sprint plannnig, sprint (development), sprint review, retrospec (analyzing the sprint). The goal is to end up with potentially shippable products.
+An Agile [framework](https://www.scrum.org/Resources/What-is-Scrum) designed to typically help complete complex software projects. It's made up of several parts: product requirements backlog, sprint planning, sprint (development), sprint review, and retrospec (analyzing the sprint). The goal is to end up with potentially shippable products.
### Scrum Board
The board used to track the status and progress of each of the sprint backlog items.
+### Shell
+
+Terminal on Mac OSX, GitBash on Windows, or Linux Terminal on Linux. You [use git]() and make changes to GitLab projects in your shell. You [use git](https://docs.gitlab.com/ce/gitlab-basics/start-using-git.html) and make changes to GitLab projects in your shell.
+
+### Single-tenant
+
+The tenant purchases their own copy of the software and the software can be customized to meet the specific and needs of that customer. [GitHost.io](https://about.gitlab.com/handbook/positioning-faq/) is our provider of single-tenant 'managed cloud' GitLab instances.
+
### Slack
-Real time messaging app for teams. Used internally by GitLab
+Real time messaging app for teams that is used internally by GitLab team members. GitLab users can enable [Slack integration](https://docs.gitlab.com/ce/project_services/slack.html) to trigger push, issue, and merge request events among others.
### Slave Servers
-Also known as secondary servers. They help to spread the load over multiple machines, they also provide backups when the master/primary server crashes.
+Also known as secondary servers, these help to spread the load over multiple machines. They also provide backups when the master/primary server crashes.
### Source Code
-Program code as typed by a computer programmer. i.e. it has not yet been compiled/translated by the computer to machine language.
+Program code as typed by a computer programmer (i.e. it has not yet been compiled/translated by the computer to machine language).
### SSH Key
-A unique identifier of a computer. It is used to identify computers without the need for a password. e.g. On GitLab I have added the ssh key of all my work machines so that the GitLab instance knows that it can accept code pushes and pulls from this trusted machines whose keys are I have added.
+A unique identifier of a computer. It is used to identify computers without the need for a password (e.g., On GitLab I have [added the ssh key](https://docs.gitlab.com/ce/gitlab-basics/create-your-ssh-keys.html) of all my work machines so that the GitLab instance knows that it can accept code pushes and pulls from this trusted machines whose keys are I have added.)
-### SSO
+### Single Sign On (SSO)
-Single Sign On. An authentication process that allows you enter one username and password to access multiple applications.
+An authentication process that allows you enter one username and password to access multiple applications.
+
+### Staging Area
+
+[Staging occurs](https://git-scm.com/book/en/v2/Getting-Started-Git-Basics) before the commit process in git. The staging area is a file, generally contained in your Git directory, that stores information about what will go into your next commit. It’s sometimes referred to as the “index.""
### Standard Subscription
-Our mid range EE subscription that includes 24/7 support, support for High Availability [Standard Subscription](https://about.gitlab.com/pricing/)
+Our mid range EE subscription that includes 24/7 support and support for High Availability [Standard Subscription](https://about.gitlab.com/pricing/).
### Stash
-Atlassian's Git On-Premises solution. Think of it as Atlassian's GitLab EE. It is now known as BitBucket Server.
+Atlassian's Git on-premise solution. Think of it as Atlassian's GitLab EE, now known as BitBucket Server.
+
+### Static Site Generators (SSGs)
+
+A [software](https://wiki.python.org/moin/StaticSiteGenerator) that takes some text and templates as input and produces html files on the output.
### Subversion
@@ -443,40 +528,65 @@ Non-proprietary, centralized version control system.
### Sudo
-A program that allows you to perform superuser/administrator actions on Unix Operating Systems e.g. Linux, OS X. It actually stands for 'superuser do'
+A program that allows you to perform superuser/administrator actions on Unix Operating Systems (e.g., Linux, OS X.) It actually stands for 'superuser do.'
-### SVN
+### Subversion (SVN)
-Abbreviation for Subversion.
+An open source version control system. Read about [migrating from SVN](https://docs.gitlab.com/ce/workflow/importing/migrating_from_svn.html) to GitLab using SubGit.
### Tag
-Represents a version of a particular branch at a moment in time.
+[Represents](https://docs.gitlab.com/ce/api/tags.html) a version of a particular branch at a moment in time.
### Tool Stack
-Set of tools used in a process to achieve a common outcome. E.g. set of tools used in Application Lifecycle Management.
+The set of tools used in a process to achieve a common outcome (e.g. set of tools used in Application Lifecycle Management).
### Trac
-An Open Source project management and bug tracking web application.
+An open source project management and bug tracking web [application](https://trac.edgewall.org/).
+
+### Untracked files
+
+New files that Git has not [been told](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository) to track previously.
### User
Anyone interacting with the software.
-### VCS
+### Version Control Software (VCS)
+
+Version control is a system that records changes to a file or set of files over time so that you can recall specific versions later. VCS [has evolved](https://docs.google.com/presentation/d/16sX7hUrCZyOFbpvnrAFrg6tVO5_yT98IgdAqOmXwBho/edit#slide=id.gd69537a19_0_32) from local version control systems, to centralized version control systems, to the present distributed version control systems like Git, Mercurial, Bazaar, and Darcs.
+
+### Virtual Private Cloud (VPC)
+
+An on demand configurable pool of shared computing resources allocated within a public cloud environment, providing some isolation between the different users using the resources. GitLab users need to create a new Amazon VPC in order to [setup High Availability](https://docs.gitlab.com/ce/university/high-availability/aws/).
-Version Control Software
+### Virtual private server (VPS)
+
+A [virtual machine](https://en.wikipedia.org/wiki/Virtual_private_server) sold as a service by an Internet hosting service. A VPS runs its own copy of an operating system, and customers have superuser-level access to that operating system instance, so they can install almost any software that runs on that OS.
+
+### VM Instance
+
+In object-oriented programming, an [instance](http://stackoverflow.com/questions/20461907/what-is-meaning-of-instance-in-programming) is a specific realization of any object. An object may be varied in a number of ways. Each realized variation of that object is an instance. Therefore, a VM instance is an instance of a virtual machine, which is an emulation of a computer system.
### Waterfall
-A model of building software that involves collecting all requirements from the customer, then building and refining all the requirements and finally delivering the COMPLETE software to the customer that meets all the requirements specified by the customer
+A [model](http://www.umsl.edu/~hugheyd/is6840/waterfall.html) of building software that involves collecting all requirements from the customer, then building and refining all the requirements and finally delivering the complete software to the customer that meets all the requirements they specified.
### Webhooks
-A way for for an app to provide other applications with real-time information. e.g. send a message to a slack channel when a commit is pushed
+A way for for an app to [provide](https://docs.gitlab.com/ce/user/project/integrations/webhooks.html) other applications with real-time information (e.g., send a message to a slack channel when a commit is pushed.) Read about setting up [custom git hooks](https://gitlab.com/help/administration/custom_hooks.md) for when webhooks are insufficient.
### Wiki
-A website/system that allows for collaborative editing of its content by the users. In programming, they usually contain documentation of how to use the software
+A [website/system](http://www.wiki.com/) that allows for collaborative editing of its content by the users. In programming, wikis usually contain documentation of how to use the software.
+
+### Working Tree
+
+[Consists of files](http://stackoverflow.com/questions/3689838/difference-between-head-working-tree-index-in-git) that you are currently working on.
+
+### YAML
+
+A human-readable data serialization [language](http://www.yaml.org/about.html) that takes concepts from programming languages such as C, Perl, and Python, and ideas from XML and the data format of electronic mail.
+
diff --git a/doc/university/high-availability/aws/README.md b/doc/university/high-availability/aws/README.md
index 088f1cd7290..6b8f3cd3d1d 100644
--- a/doc/university/high-availability/aws/README.md
+++ b/doc/university/high-availability/aws/README.md
@@ -159,19 +159,21 @@ subnet and security group and
***
-## Elastic File System
+## Network File System
-This new AWS offering allows us to create a file system accessible by

-EC2 instances within a VPC. Choose our VPC and the subnets will be
-
automatically configured assuming we don't need to set explicit IPs.
-The
next section allows us to add tags and choose between General
-Purpose or
Max I/O which is a good option when being accessed by a
-large number of
EC2 instances.
+GitLab requires a shared filesystem such as NFS. The file share(s) will be
+mounted on all application servers. There are a variety of ways to build an
+NFS server on AWS.
-

![Elastic File System](img/elastic-file-system.png)
+One option is to use a third-party AMI that offers NFS as a service. A [search
+for 'NFS' in the AWS Marketplace](https://aws.amazon.com/marketplace/search/results?x=0&y=0&searchTerms=NFS&page=1&ref_=nav_search_box)
+shows options such as NetApp, SoftNAS and others.
-To actually mount and install the NFS client we'll use the User Data
-section when adding our Launch Configuration.
+Another option is to build a simple NFS server using a vanilla Linux server backed
+by AWS Elastic Block Storage (EBS).
+
+> **Note:** GitLab does not recommend using AWS Elastic File System (EFS). See
+ details in [High Availability NFS documentation](../../../administration/high_availability/nfs.md#aws-elastic-file-system)
***
diff --git a/doc/university/high-availability/aws/img/auto-scaling-det.png b/doc/university/high-availability/aws/img/auto-scaling-det.png
index e9b65529495..1e125f301bc 100644
--- a/doc/university/high-availability/aws/img/auto-scaling-det.png
+++ b/doc/university/high-availability/aws/img/auto-scaling-det.png
Binary files differ
diff --git a/doc/university/high-availability/aws/img/db-subnet-group.png b/doc/university/high-availability/aws/img/db-subnet-group.png
index 0768aa73c45..590a02b8dbe 100644
--- a/doc/university/high-availability/aws/img/db-subnet-group.png
+++ b/doc/university/high-availability/aws/img/db-subnet-group.png
Binary files differ
diff --git a/doc/university/high-availability/aws/img/ec-subnet.png b/doc/university/high-availability/aws/img/ec-subnet.png
index f41d78b271d..43ef76b62d3 100644
--- a/doc/university/high-availability/aws/img/ec-subnet.png
+++ b/doc/university/high-availability/aws/img/ec-subnet.png
Binary files differ
diff --git a/doc/university/high-availability/aws/img/elastic-file-system.png b/doc/university/high-availability/aws/img/elastic-file-system.png
index 7de866d1e89..5bcfb8d0588 100644
--- a/doc/university/high-availability/aws/img/elastic-file-system.png
+++ b/doc/university/high-availability/aws/img/elastic-file-system.png
Binary files differ
diff --git a/doc/university/high-availability/aws/img/ig-rt.png b/doc/university/high-availability/aws/img/ig-rt.png
index 93bb0c2ae02..62cca074a1e 100644
--- a/doc/university/high-availability/aws/img/ig-rt.png
+++ b/doc/university/high-availability/aws/img/ig-rt.png
Binary files differ
diff --git a/doc/university/high-availability/aws/img/ig.png b/doc/university/high-availability/aws/img/ig.png
index cc50456370f..d4fc2d12de8 100644
--- a/doc/university/high-availability/aws/img/ig.png
+++ b/doc/university/high-availability/aws/img/ig.png
Binary files differ
diff --git a/doc/university/high-availability/aws/img/instance_specs.png b/doc/university/high-availability/aws/img/instance_specs.png
index ef31dc41dae..650f375ab3c 100644
--- a/doc/university/high-availability/aws/img/instance_specs.png
+++ b/doc/university/high-availability/aws/img/instance_specs.png
Binary files differ
diff --git a/doc/university/high-availability/aws/img/new_vpc.png b/doc/university/high-availability/aws/img/new_vpc.png
index 4aac6af7c7a..e51c066cee2 100644
--- a/doc/university/high-availability/aws/img/new_vpc.png
+++ b/doc/university/high-availability/aws/img/new_vpc.png
Binary files differ
diff --git a/doc/university/high-availability/aws/img/policies.png b/doc/university/high-availability/aws/img/policies.png
index 8c58117e4fa..afcd9e4af9b 100644
--- a/doc/university/high-availability/aws/img/policies.png
+++ b/doc/university/high-availability/aws/img/policies.png
Binary files differ
diff --git a/doc/university/high-availability/aws/img/rds-net-opt.png b/doc/university/high-availability/aws/img/rds-net-opt.png
index bc204de2474..651cc23b1ab 100644
--- a/doc/university/high-availability/aws/img/rds-net-opt.png
+++ b/doc/university/high-availability/aws/img/rds-net-opt.png
Binary files differ
diff --git a/doc/university/high-availability/aws/img/rds-sec-group.png b/doc/university/high-availability/aws/img/rds-sec-group.png
index 8864dc3e463..c6d1bc350e4 100644
--- a/doc/university/high-availability/aws/img/rds-sec-group.png
+++ b/doc/university/high-availability/aws/img/rds-sec-group.png
Binary files differ
diff --git a/doc/university/high-availability/aws/img/redis-cluster-det.png b/doc/university/high-availability/aws/img/redis-cluster-det.png
index 9e9a81283c5..51d3a08eab6 100644
--- a/doc/university/high-availability/aws/img/redis-cluster-det.png
+++ b/doc/university/high-availability/aws/img/redis-cluster-det.png
Binary files differ
diff --git a/doc/university/high-availability/aws/img/redis-net.png b/doc/university/high-availability/aws/img/redis-net.png
index 037bd6d6897..9022a9ada78 100644
--- a/doc/university/high-availability/aws/img/redis-net.png
+++ b/doc/university/high-availability/aws/img/redis-net.png
Binary files differ
diff --git a/doc/university/high-availability/aws/img/route_table.png b/doc/university/high-availability/aws/img/route_table.png
index 1dea322474d..c8bef75f01a 100644
--- a/doc/university/high-availability/aws/img/route_table.png
+++ b/doc/university/high-availability/aws/img/route_table.png
Binary files differ
diff --git a/doc/university/high-availability/aws/img/subnet.png b/doc/university/high-availability/aws/img/subnet.png
index dbc71201992..de910edc948 100644
--- a/doc/university/high-availability/aws/img/subnet.png
+++ b/doc/university/high-availability/aws/img/subnet.png
Binary files differ
diff --git a/doc/university/support/README.md b/doc/university/support/README.md
index da991e56370..567dadb3b47 100644
--- a/doc/university/support/README.md
+++ b/doc/university/support/README.md
@@ -58,28 +58,28 @@ Sometimes we need to upgrade customers from old versions of GitLab to latest, so
- Users
- Groups
- Projects
- - [Backup using our Backup rake task](http://docs.gitlab.com/ce/raketasks/backup_restore.html#create-a-backup-of-the-gitlab-system)
+ - [Backup using our Backup rake task](https://docs.gitlab.com/ce/raketasks/backup_restore.html#create-a-backup-of-the-gitlab-system)
- [Upgrade to 5.0 source using our Upgrade documentation](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/doc/update/4.2-to-5.0.md)
- [Upgrade to 5.1 source](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/doc/update/5.0-to-5.1.md)
- [Upgrade to 6.0 source](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/doc/update/5.1-to-6.0.md)
- [Upgrade to 7.14 source](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/doc/update/6.x-or-7.x-to-7.14.md)
- - [Backup using our Backup rake task](http://docs.gitlab.com/ce/raketasks/backup_restore.html#create-a-backup-of-the-gitlab-system)
- - [Perform the MySQL to PostgreSQL migration to convert your backup](http://docs.gitlab.com/ce/update/mysql_to_postgresql.html#converting-a-gitlab-backup-file-from-mysql-to-postgres)
- - [Upgrade to Omnibus 7.14](http://doc.gitlab.com/omnibus/update/README.html#upgrading-from-a-non-omnibus-installation-to-an-omnibus-installation)
- - [Restore backup using our Restore rake task](http://docs.gitlab.com/ce/raketasks/backup_restore.html#restore-a-previously-created-backup)
+ - [Backup using our Backup rake task](https://docs.gitlab.com/ce/raketasks/backup_restore.html#create-a-backup-of-the-gitlab-system)
+ - [Perform the MySQL to PostgreSQL migration to convert your backup](https://docs.gitlab.com/ce/update/mysql_to_postgresql.html#converting-a-gitlab-backup-file-from-mysql-to-postgres)
+ - [Upgrade to Omnibus 7.14](https://docs.gitlab.com/omnibus/update/README.html#upgrading-from-a-non-omnibus-installation-to-an-omnibus-installation)
+ - [Restore backup using our Restore rake task](https://docs.gitlab.com/ce/raketasks/backup_restore.html#restore-a-previously-created-backup)
- [Upgrade to latest EE](https://about.gitlab.com/downloads-ee)
- (GitLab inc. only) Acquire and apply a license for the Enterprise Edition product, ask in #support
-- Perform a downgrade from [EE to CE](http://doc.gitlab.com/ee/downgrade_ee_to_ce/README.html)
+- Perform a downgrade from [EE to CE](https://docs.gitlab.com/ee/downgrade_ee_to_ce/README.html)
#### Start to learn about some of the integrations that we support
Our integrations add great value to GitLab. User questions often relate to integrating GitLab with existing external services and the configuration involved
- Learn about our Integrations (specially, not only):
- - [LDAP](http://doc.gitlab.com/ee/integration/ldap.html)
- - [JIRA](http://doc.gitlab.com/ee/project_services/jira.html)
- - [Jenkins](http://doc.gitlab.com/ee/integration/jenkins.html)
- - [SAML](http://doc.gitlab.com/ce/integration/saml.html)
+ - [LDAP](https://docs.gitlab.com/ee/integration/ldap.html)
+ - [JIRA](https://docs.gitlab.com/ee/project_services/jira.html)
+ - [Jenkins](https://docs.gitlab.com/ee/integration/jenkins.html)
+ - [SAML](https://docs.gitlab.com/ce/integration/saml.html)
#### Goals
@@ -91,8 +91,8 @@ Our integrations add great value to GitLab. User questions often relate to integ
#### Understand the gathering of diagnostics for GitLab instances
- Learn about the GitLab checks that are available
- - [Environment Information and maintenance checks](http://docs.gitlab.com/ce/raketasks/maintenance.html)
- - [GitLab check](http://docs.gitlab.com/ce/raketasks/check.html)
+ - [Environment Information and maintenance checks](https://docs.gitlab.com/ce/raketasks/maintenance.html)
+ - [GitLab check](https://docs.gitlab.com/ce/raketasks/check.html)
- Omnibus commands
- [Status](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/maintenance/README.md#get-service-status)
- [Starting and stopping services](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/maintenance/README.md#starting-and-stopping)
@@ -167,12 +167,11 @@ Some tickets need specific knowledge or a deep understanding of a particular com
Move on to understanding some of GitLab's more advanced features. You can make use of GitLab.com to understand the features from an end-user perspective and then use your own instance to understand setup and configuration of the feature from an Administrative perspective
-- Set up and try [Git Annex](http://doc.gitlab.com/ee/workflow/git_annex.html)
-- Set up and try [Git LFS](http://doc.gitlab.com/ee/workflow/lfs/manage_large_binaries_with_git_lfs.html)
-- Get to know the [GitLab API](http://doc.gitlab.com/ee/api/README.html), its capabilities and shortcomings
-- Learn how to [migrate from SVN to Git](http://doc.gitlab.com/ee/workflow/importing/migrating_from_svn.html)
-- Set up [GitLab CI](http://doc.gitlab.com/ee/ci/quick_start/README.html)
-- Create your first [GitLab Page](http://doc.gitlab.com/ee/pages/administration.html)
+- Set up and try [Git LFS](https://docs.gitlab.com/ee/workflow/lfs/manage_large_binaries_with_git_lfs.html)
+- Get to know the [GitLab API](https://docs.gitlab.com/ee/api/README.html), its capabilities and shortcomings
+- Learn how to [migrate from SVN to Git](https://docs.gitlab.com/ee/workflow/importing/migrating_from_svn.html)
+- Set up [GitLab CI](https://docs.gitlab.com/ee/ci/quick_start/README.html)
+- Create your first [GitLab Page](https://docs.gitlab.com/ce/administration/pages/)
- Get to know the GitLab Codebase by reading through the source code:
- Find the differences between the [EE codebase](https://gitlab.com/gitlab-org/gitlab-ce)
and the [CE codebase](https://gitlab.com/gitlab-org/gitlab-ce)
diff --git a/doc/university/training/gitlab_flow.md b/doc/university/training/gitlab_flow.md
new file mode 100755
index 00000000000..a7db1f2e069
--- /dev/null
+++ b/doc/university/training/gitlab_flow.md
@@ -0,0 +1,53 @@
+# GitLab Flow
+
+- A simplified branching strategy
+- All features and fixes first go to master
+- Allows for 'production' or 'stable' branches
+- Bug fixes/hot fix patches are cherry-picked from master
+
+---
+
+# Feature branches
+
+- Create a feature/bugfix branch to do all work
+- Use merge requests to merge to master
+
+![inline](gitlab_flow/feature_branches.png)
+
+---
+
+# Production branch
+
+- One, long-running production release branch
+ as opposed to individual stable branches
+- Consider creating a tag for each version that gets deployed
+
+---
+
+# Production branch
+
+![inline](gitlab_flow/production_branch.png)
+
+---
+
+# Release branch
+
+- Useful if you release software to customers
+- When preparing a new release, create stable branch
+ from master
+- Consider creating a tag for each version
+- Cherry-pick critical bug fixes to stable branch for patch release
+- Never commit bug fixes directly to stable branch
+
+---
+
+# Release branch
+
+![inline](gitlab_flow/release_branches.png)
+
+---
+
+# More details
+
+Blog post on 'GitLab Flow' at
+[http://doc.gitlab.com/ee/workflow/gitlab_flow.html](http://doc.gitlab.com/ee/workflow/gitlab_flow.html)
diff --git a/doc/university/training/gitlab_flow/feature_branches.png b/doc/university/training/gitlab_flow/feature_branches.png
new file mode 100644
index 00000000000..612e0248222
--- /dev/null
+++ b/doc/university/training/gitlab_flow/feature_branches.png
Binary files differ
diff --git a/doc/university/training/gitlab_flow/production_branch.png b/doc/university/training/gitlab_flow/production_branch.png
new file mode 100644
index 00000000000..66456cc51af
--- /dev/null
+++ b/doc/university/training/gitlab_flow/production_branch.png
Binary files differ
diff --git a/doc/university/training/gitlab_flow/release_branches.png b/doc/university/training/gitlab_flow/release_branches.png
new file mode 100644
index 00000000000..5661e36c4e2
--- /dev/null
+++ b/doc/university/training/gitlab_flow/release_branches.png
Binary files differ
diff --git a/doc/university/training/index.md b/doc/university/training/index.md
new file mode 100755
index 00000000000..03179ff5a77
--- /dev/null
+++ b/doc/university/training/index.md
@@ -0,0 +1,6 @@
+# GitLab Training Material
+
+All GitLab training material is stored in markdown format. Slides are
+generated using [Deskset](http://www.decksetapp.com/).
+
+All training material is open to public contribution.
diff --git a/doc/university/training/logo.png b/doc/university/training/logo.png
new file mode 100644
index 00000000000..c80f65c053e
--- /dev/null
+++ b/doc/university/training/logo.png
Binary files differ
diff --git a/doc/university/training/topics/additional_resources.md b/doc/university/training/topics/additional_resources.md
new file mode 100755
index 00000000000..3ed601625cf
--- /dev/null
+++ b/doc/university/training/topics/additional_resources.md
@@ -0,0 +1,8 @@
+## Additional Resources
+
+1. GitLab Documentation [http://docs.gitlab.com](http://docs.gitlab.com/)
+2. GUI Clients [http://git-scm.com/downloads/guis](http://git-scm.com/downloads/guis)
+3. Pro git book [http://git-scm.com/book](http://git-scm.com/book)
+4. Platzi Course [https://courses.platzi.com/courses/git-gitlab/](https://courses.platzi.com/courses/git-gitlab/)
+5. Code School tutorial [http://try.github.io/](http://try.github.io/)
+6. Contact Us at `subscribers@gitlab.com`
diff --git a/doc/university/training/topics/agile_git.md b/doc/university/training/topics/agile_git.md
new file mode 100755
index 00000000000..e6e4fea9b51
--- /dev/null
+++ b/doc/university/training/topics/agile_git.md
@@ -0,0 +1,33 @@
+# Agile and Git
+
+----------
+
+## Agile
+
+Lean software development methods focused on collaboration and interaction
+with fast and smaller deployment cycles.
+
+----------
+
+## Where Git comes in
+
+Git is an excellent tool for an Agile team considering that it allows
+decentralized and simultaneous development.
+
+----------
+
+### Branching And Workflows
+
+Branching in an Agile environment usually happens around user stories with one
+or more developers working on it.
+
+If more than one developer then another branch for each developer is also used
+with his/her initials, and US id.
+
+After its tested merge into master and remove the branch.
+
+----------
+
+## What about GitLab
+Tools like GitLab enhance collaboration by adding dialog around code mainly
+through issues and merge requests.
diff --git a/doc/university/training/topics/bisect.md b/doc/university/training/topics/bisect.md
new file mode 100755
index 00000000000..a60c4365e0c
--- /dev/null
+++ b/doc/university/training/topics/bisect.md
@@ -0,0 +1,81 @@
+# Bisect
+
+----------
+
+## Bisect
+
+- Find a commit that introduced a bug
+- Works through a process of elimination
+- Specify a known good and bad revision to begin
+
+----------
+
+## Bisect
+
+1. Start the bisect process
+2. Enter the bad revision (usually latest commit)
+3. Enter a known good revision (commit/branch)
+4. Run code to see if bug still exists
+5. Tell bisect the result
+6. Repeat the previous 2 items until you find the offending commit
+
+----------
+
+## Setup
+
+```
+ mkdir bisect-ex
+ cd bisect-ex
+ touch index.html
+ git add -A
+ git commit -m "starting out"
+ vi index.html
+ # Add all good
+ git add -A
+ git commit -m "second commit"
+ vi index.html
+ # Add all good 2
+ git add -A
+ git commit -m "third commit"
+ vi index.html
+```
+
+----------
+
+```
+ # Add all good 3
+ git add -A
+ git commit -m "fourth commit"
+ vi index.html
+ # This looks bad
+ git add -A
+ git commit -m "fifth commit"
+ vi index.html
+ # Really bad
+ git add -A
+ git commit -m "sixth commit"
+ vi index.html
+ # again just bad
+ git add -A
+ git commit -m "seventh commit"
+```
+
+----------
+
+## Commands
+
+```
+ git bisect start
+ # Test your code
+ git bisect bad
+ git bisect next
+ # Say yes to the warning
+ # Test
+ git bisect good
+ # Test
+ git bisect bad
+ # Test
+ git bisect good
+ # done
+ git bisect reset
+```
diff --git a/doc/university/training/topics/cherry_picking.md b/doc/university/training/topics/cherry_picking.md
new file mode 100755
index 00000000000..af7a70a2818
--- /dev/null
+++ b/doc/university/training/topics/cherry_picking.md
@@ -0,0 +1,39 @@
+# Cherry Pick
+
+----------
+
+## Cherry Pick
+
+- Given an existing commit on one branch, apply the change to another branch
+- Useful for backporting bug fixes to previous release branches
+- Make the commit on the master branch and pick in to stable
+
+----------
+
+## Cherry Pick
+
+1. Check out a new 'stable' branch from 'master'
+1. Change back to 'master'
+1. Edit '`cherry_pick.rb`' and commit the changes.
+1. Check commit log to get the commit SHA
+1. Check out the 'stable' branch
+1. Cherry pick the commit using the SHA obtained earlier
+
+----------
+
+## Commands
+
+```bash
+git checkout master
+git checkout -b stable
+git checkout master
+
+# Edit `cherry_pick.rb`
+git add cherry_pick.rb
+git commit -m 'Fix bugs in cherry_pick.rb'
+git log
+# Copy commit SHA
+git checkout stable
+
+git cherry-pick <commit SHA>
+```
diff --git a/doc/university/training/topics/env_setup.md b/doc/university/training/topics/env_setup.md
new file mode 100755
index 00000000000..8149379b36f
--- /dev/null
+++ b/doc/university/training/topics/env_setup.md
@@ -0,0 +1,60 @@
+# Configure your environment
+
+----------
+## Install
+
+- **Windows**
+ - Install 'Git for Windows' from https://git-for-windows.github.io
+
+- **Mac**
+ - Type '`git`' in the Terminal application.
+ - If it's not installed, it will prompt you to install it.
+
+- **Linux**
+ ```bash
+ sudo yum install git-all
+ ```
+ ```bash
+ sudo apt-get install git-all
+ ```
+
+----------
+
+## Configure Git
+
+One-time configuration of the Git client
+
+```bash
+git config --global user.name "Your Name"
+git config --global user.email you@example.com
+```
+
+----------
+
+## Configure SSH Key
+
+```bash
+ssh-keygen -t rsa -b 4096 -C "you@computer-name"
+```
+
+```bash
+# You will be prompted for the following information. Press enter to accept the defaults. Defaults appear in parentheses.
+Generating public/private rsa key pair.
+Enter file in which to save the key (/Users/you/.ssh/id_rsa):
+Enter passphrase (empty for no passphrase):
+Enter same passphrase again:
+Your identification has been saved in /Users/you/.ssh/id_rsa.
+Your public key has been saved in /Users/you/.ssh/id_rsa.pub.
+The key fingerprint is:
+39:fc:ce:94:f4:09:13:95:64:9a:65:c1:de:05:4d:01 you@computer-name
+```
+
+Copy your public key and add it to your GitLab profile
+
+```bash
+cat ~/.ssh/id_rsa.pub
+```
+
+```bash
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQEL17Ufacg8cDhlQMS5NhV8z3GHZdhCrZbl4gz you@example.com
+```
diff --git a/doc/university/training/topics/explore_gitlab.md b/doc/university/training/topics/explore_gitlab.md
new file mode 100755
index 00000000000..b65457728c0
--- /dev/null
+++ b/doc/university/training/topics/explore_gitlab.md
@@ -0,0 +1,10 @@
+# Explore GitLab projects
+
+----------
+
+- Dashboard
+- User Preferences
+- Issues
+- Milestones and Labels
+- Manage project members
+- Project settings
diff --git a/doc/university/training/topics/feature_branching.md b/doc/university/training/topics/feature_branching.md
new file mode 100755
index 00000000000..4b34406ea75
--- /dev/null
+++ b/doc/university/training/topics/feature_branching.md
@@ -0,0 +1,32 @@
+# Feature branching
+
+----------
+
+- Efficient parallel workflow for teams
+- Develop each feature in a branch
+- Keeps changes isolated
+- Consider a 1-to-1 link to issues
+- Push branches to the server frequently
+ - Hint: This is a cheap backup for your work-in-progress code
+
+----------
+
+## Feature branching
+
+1. Create a new feature branch called 'squash_some_bugs'
+1. Edit '`bugs.rb`' and remove all the bugs.
+1. Commit
+1. Push
+
+----------
+
+## Commands
+
+```
+git checkout -b squash_some_bugs
+# Edit `bugs.rb`
+git status
+git add bugs.rb
+git commit -m 'Fix some buggy code'
+git push origin squash_some_bugs
+```
diff --git a/doc/university/training/topics/getting_started.md b/doc/university/training/topics/getting_started.md
new file mode 100755
index 00000000000..ec7bb2631aa
--- /dev/null
+++ b/doc/university/training/topics/getting_started.md
@@ -0,0 +1,95 @@
+# Getting Started
+
+----------
+
+## Instantiating Repositories
+
+* Create a new repository by instantiating it through
+```bash
+git init
+```
+* Copy an existing project by cloning the repository through
+```bash
+git clone <url>
+```
+
+----------
+
+## Central Repos
+
+* To instantiate a central repository a `--bare` flag is required.
+* Bare repositories don't allow file editing or committing changes.
+* Create a bare repo with
+```bash
+git init --bare project-name.git
+```
+
+----------
+
+## Instantiate workflow with clone
+
+1. Create a project in your user namespace
+ - Choose to import from 'Any Repo by URL' and use
+ https://gitlab.com/gitlab-org/training-examples.git
+2. Create a '`Workspace`' directory in your home directory.
+3. Clone the '`training-examples`' project
+
+----------
+
+## Commands
+
+```
+mkdir ~/workspace
+cd ~/workspace
+
+git clone git@gitlab.example.com:<username>/training-examples.git
+cd training-examples
+```
+----------
+
+## Git concepts
+
+**Untracked files**
+
+New files that Git has not been told to track previously.
+
+**Working area**
+
+Files that have been modified but are not committed.
+
+**Staging area**
+
+Modified files that have been marked to go in the next commit.
+
+----------
+
+## Committing Workflow
+
+1. Edit '`edit_this_file.rb`' in '`training-examples`'
+1. See it listed as a changed file (working area)
+1. View the differences
+1. Stage the file
+1. Commit
+1. Push the commit to the remote
+1. View the git log
+
+----------
+
+## Commands
+
+```
+# Edit `edit_this_file.rb`
+git status
+git diff
+git add <file>
+git commit -m 'My change'
+git push origin master
+git log
+```
+
+----------
+
+## Note
+
+* git fetch vs pull
+* Pull is git fetch + git merge
diff --git a/doc/university/training/topics/git_add.md b/doc/university/training/topics/git_add.md
new file mode 100755
index 00000000000..9ffb4b9c859
--- /dev/null
+++ b/doc/university/training/topics/git_add.md
@@ -0,0 +1,33 @@
+# Git Add
+
+----------
+
+## Git Add
+
+Adds content to the index or staging area.
+
+* Adds a list of file
+```bash
+git add <files>
+```
+* Adds all files including deleted ones
+```bash
+git add -A
+```
+
+----------
+
+## Git add continued
+
+* Add all text files in current dir
+```bash
+git add *.txt
+```
+* Add all text file in the project
+```bash
+git add "*.txt*"
+```
+* Adds all files in directory
+```bash
+git add views/layouts/
+```
diff --git a/doc/university/training/topics/git_intro.md b/doc/university/training/topics/git_intro.md
new file mode 100755
index 00000000000..ca1ff29d93b
--- /dev/null
+++ b/doc/university/training/topics/git_intro.md
@@ -0,0 +1,24 @@
+# Git introduction
+
+----------
+
+## Intro
+
+https://git-scm.com/about
+
+- Distributed version control
+ - Does not rely on connection to a central server
+ - Many copies of the complete history
+- Powerful branching and merging
+- Adapts to nearly any workflow
+- Fast, reliable and stable file format
+
+----------
+
+## Help!
+
+Use the tools at your disposal when you get stuck.
+
+- Use '`git help <command>`' command
+- Use Google
+- Read documentation at https://git-scm.com
diff --git a/doc/university/training/topics/git_log.md b/doc/university/training/topics/git_log.md
new file mode 100755
index 00000000000..32ebceff491
--- /dev/null
+++ b/doc/university/training/topics/git_log.md
@@ -0,0 +1,57 @@
+# Git Log
+
+----------
+
+Git log lists commit history. It allows searching and filtering.
+
+* Initiate log
+```
+git log
+```
+
+* Retrieve set number of records:
+```
+git log -n 2
+```
+
+* Search commits by author. Allows user name or a regular expression.
+```
+git log --author="user_name"
+```
+
+----------
+
+* Search by comment message.
+```
+git log --grep="<pattern>"
+```
+
+* Search by date
+```
+git log --since=1.month.ago --until=3.weeks.ago
+```
+
+
+----------
+
+## Git Log Workflow
+
+1. Change to workspace directory
+2. Clone the multi runner projects
+3. Change to project dir
+4. Search by author
+5. Search by date
+6. Combine
+
+----------
+
+## Commands
+
+```
+cd ~/workspace
+git clone git@gitlab.com:gitlab-org/gitlab-ci-multi-runner.git
+cd gitlab-ci-multi-runner
+git log --author="Travis"
+git log --since=1.month.ago --until=3.weeks.ago
+git log --since=1.month.ago --until=1.day.ago --author="Travis"
+```
diff --git a/doc/university/training/topics/gitlab_flow.md b/doc/university/training/topics/gitlab_flow.md
new file mode 100755
index 00000000000..8e5d3baf959
--- /dev/null
+++ b/doc/university/training/topics/gitlab_flow.md
@@ -0,0 +1,53 @@
+# GitLab Flow
+
+----------
+
+- A simplified branching strategy
+- All features and fixes first go to master
+- Allows for 'production' or 'stable' branches
+- Bug fixes/hot fix patches are cherry-picked from master
+
+----------
+
+### Feature branches
+
+- Create a feature/bugfix branch to do all work
+- Use merge requests to merge to master
+
+![inline](http://gitlab.com/gitlab-org/University/raw/5baea0fe222a915d0500e40747d35eb18681cdc3/training/gitlab_flow/feature_branches.png)
+
+----------
+
+## Production branch
+
+- One, long-running production release branch
+ as opposed to individual stable branches
+- Consider creating a tag for each version that gets deployed
+
+----------
+
+## Production branch
+
+![inline](http://gitlab.com/gitlab-org/University/raw/5baea0fe222a915d0500e40747d35eb18681cdc3/training/gitlab_flow/production_branch.png)
+
+----------
+
+## Release branch
+
+- Useful if you release software to customers
+- When preparing a new release, create stable branch
+ from master
+- Consider creating a tag for each version
+- Cherry-pick critical bug fixes to stable branch for patch release
+- Never commit bug fixes directly to stable branch
+
+----------
+
+![inline](http://gitlab.com/gitlab-org/University/raw/5baea0fe222a915d0500e40747d35eb18681cdc3/training/gitlab_flow/release_branches.png)
+
+----------
+
+## More details
+
+Blog post on 'GitLab Flow' at
+[http://doc.gitlab.com/ee/workflow/gitlab_flow.html](http://doc.gitlab.com/ee/workflow/gitlab_flow.html)
diff --git a/doc/university/training/topics/merge_conflicts.md b/doc/university/training/topics/merge_conflicts.md
new file mode 100755
index 00000000000..77807b3e7ef
--- /dev/null
+++ b/doc/university/training/topics/merge_conflicts.md
@@ -0,0 +1,70 @@
+# Merge conflicts
+
+----------
+
+- Happen often
+- Learning to fix conflicts is hard
+- Practice makes perfect
+- Force push after fixing conflicts. Be careful!
+
+----------
+
+## Merge conflicts
+
+1. Checkout a new branch and edit `conflicts.rb`. Add 'Line4' and 'Line5'.
+2. Commit and push
+3. Checkout master and edit `conflicts.rb`. Add 'Line6' and 'Line7' below 'Line3'.
+4. Commit and push to master
+5. Create a merge request and watch it fail
+6. Rebase our new branch with master
+7. Fix conflicts on the `conflicts.rb` file.
+8. Stage the file and continue rebasing
+9. Force push the changes
+10. Finally continue with the Merge Request
+
+----------
+
+## Commands
+
+```
+git checkout -b conflicts_branch
+
+# vi conflicts.rb
+# Add 'Line4' and 'Line5'
+
+git commit -am "add line4 and line5"
+git push origin conflicts_branch
+
+git checkout master
+
+# vi conflicts.rb
+# Add 'Line6' and 'Line7'
+git commit -am "add line6 and line7"
+git push origin master
+```
+
+Create a merge request on the GitLab web UI. You'll see a conflict warning.
+
+```
+git checkout conflicts_branch
+git fetch
+git rebase master
+
+# Fix conflicts by editing the files.
+
+git add conflicts.rb
+# No need to commit this file
+
+git rebase --continue
+
+# Remember that we have rewritten our commit history so we
+# need to force push so that our remote branch is restructured
+git push origin conflicts_branch -f
+```
+----------
+
+## Note
+* When to use 'git merge' and when to use 'git rebase'
+* Rebase when updating your branch with master
+* Merge when bringing changes from feature to master
+* Reference: https://www.atlassian.com/git/tutorials/merging-vs-rebasing/
diff --git a/doc/university/training/topics/merge_requests.md b/doc/university/training/topics/merge_requests.md
new file mode 100755
index 00000000000..5b446f02f63
--- /dev/null
+++ b/doc/university/training/topics/merge_requests.md
@@ -0,0 +1,43 @@
+# Merge requests
+
+----------
+
+- When you want feedback create a merge request
+- Target is the default branch (usually master)
+- Assign or mention the person you would like to review
+- Add 'WIP' to the title if it's a work in progress
+- When accepting, always delete the branch
+- Anyone can comment, not just the assignee
+- Push corrections to the same branch
+
+----------
+
+## Merge requests
+
+**Create your first merge request**
+
+1. Use the blue button in the activity feed
+1. View the diff (changes) and leave a comment
+1. Push a new commit to the same branch
+1. Review the changes again and notice the update
+
+----------
+
+## Feedback and Collaboration
+
+- Merge requests are a time for feedback and collaboration
+- Giving feedback is hard
+- Be as kind as possible
+- Receiving feedback is hard
+- Be as receptive as possible
+- Feedback is about the best code, not the person. You are not your code
+
+----------
+
+## Feedback and Collaboration
+
+Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests:
+[https://github.com/thoughtbot/guides/tree/master/code-review](https://github.com/thoughtbot/guides/tree/master/code-review)
+
+See GitLab merge requests for examples:
+[https://gitlab.com/gitlab-org/gitlab-ce/merge_requests](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests)
diff --git a/doc/university/training/topics/rollback_commits.md b/doc/university/training/topics/rollback_commits.md
new file mode 100755
index 00000000000..cf647284604
--- /dev/null
+++ b/doc/university/training/topics/rollback_commits.md
@@ -0,0 +1,81 @@
+# Rollback Commits
+
+----------
+
+## Undo Commits
+
+* Undo last commit putting everything back into the staging area.
+```
+git reset --soft HEAD^
+```
+
+* Add files and change message with:
+```
+git commit --amend -m "New Message"
+```
+
+----------
+
+* Undo last and remove changes
+```
+git reset --hard HEAD^
+```
+
+* Same as last one but for two commits back
+```
+git reset --hard HEAD^^
+```
+
+** Don't reset after pushing **
+
+----------
+
+## Reset Workflow
+
+1. Edit file again 'edit_this_file.rb'
+2. Check status
+3. Add and commit with wrong message
+4. Check log
+5. Amend commit
+6. Check log
+7. Soft reset
+8. Check log
+9. Pull for updates
+10. Push changes
+
+
+----------
+
+## Commands
+
+```
+# Change file edit_this_file.rb
+git status
+git commit -am "kjkfjkg"
+git log
+git commit --amend -m "New comment added"
+git log
+git reset --soft HEAD^
+git log
+git pull origin master
+git push origin master
+```
+
+----------
+
+## Note
+
+* git revert vs git reset
+* Reset removes the commit while revert removes the changes but leaves the commit
+* Revert is safer considering we can revert a revert
+
+```
+# Changed file
+git commit -am "bug introduced"
+git revert HEAD
+# New commit created reverting changes
+# Now we want to re apply the reverted commit
+git log # take hash from the revert commit
+git revert <rev commit hash>
+# reverted commit is back (new commit created again)
+```
diff --git a/doc/university/training/topics/stash.md b/doc/university/training/topics/stash.md
new file mode 100755
index 00000000000..c1bdda32645
--- /dev/null
+++ b/doc/university/training/topics/stash.md
@@ -0,0 +1,86 @@
+# Git Stash
+
+----------
+
+We use git stash to store our changes when they are not ready to be committed
+and we need to change to a different branch.
+
+* Stash
+```
+git stash save
+# or
+git stash
+# or with a message
+git stash save "this is a message to display on the list"
+```
+
+* Apply stash to keep working on it
+```
+git stash apply
+# or apply a specific one from out stack
+git stash apply stash@{3}
+```
+
+----------
+
+* Every time we save a stash it gets stacked so by using list we can see all our
+stashes.
+
+```
+git stash list
+# or for more information (log methods)
+git stash list --stat
+```
+
+* To clean our stack we need to manually remove them.
+
+```
+# drop top stash
+git stash drop
+# or
+git stash drop <name>
+# to clear all history we can use
+git stash clear
+```
+
+----------
+
+* Apply and drop on one command
+
+```
+ git stash pop
+```
+
+* If we meet conflicts we need to either reset or commit our changes.
+
+* Conflicts through `pop` will not drop a stash afterwards.
+
+----------
+
+## Git Stash
+
+1. Modify a file
+2. Stage file
+3. Stash it
+4. View our stash list
+5. Confirm no pending changes through status
+5. Apply with pop
+6. View list to confirm changes
+
+----------
+
+## Commands
+
+```
+# Modify edit_this_file.rb file
+git add .
+
+git stash save "Saving changes from edit this file"
+
+git stash list
+git status
+
+git stash pop
+git stash list
+git status
+```
diff --git a/doc/university/training/topics/subtree.md b/doc/university/training/topics/subtree.md
new file mode 100755
index 00000000000..5d869af64c1
--- /dev/null
+++ b/doc/university/training/topics/subtree.md
@@ -0,0 +1,55 @@
+## Subtree
+
+----------
+
+## Subtree
+
+* Used when there are nested repositories.
+* Not recommended when the amount of dependencies is too large
+* For these cases we need a dependency control system
+* Command are painfully long so aliases are necessary
+
+----------
+
+## Subtree Aliases
+
+* Add: git subtree add --prefix <target-folder> <url> <branch> --squash
+* Pull: git subtree add --prefix <target-folder> <url> <branch> --squash
+* Push: git subtree add --prefix <target-folder> <url> <branch>
+* Ex: git config alias.sbp 'subtree pull --prefix st /
+ git@gitlab.com:balameb/subtree-nested-example.git master --squash'
+
+----------
+
+```
+ # Add an alias
+ # Add
+ git config alias.sba 'subtree add --prefix st /
+ git@gitlab.com:balameb/subtree-nested-example.git master --squash'
+ # Pull
+ git config alias.sbpl 'subtree pull --prefix st /
+ git@gitlab.com:balameb/subtree-nested-example.git master --squash'
+ # Push
+ git config alias.sbph 'subtree push --prefix st /
+ git@gitlab.com:balameb/subtree-nested-example.git master'
+
+ # Adding this subtree adds a st dir with a readme
+ git sba
+ vi st/README.md
+ # Edit file
+ git status shows differences
+
+```
+
+----------
+
+```
+ # Adding, or committing won't change the sub repo at remote
+ # even if we push
+ git add -A
+ git commit -m "Adding to subtree readme"
+
+ # Push to subtree repo
+ git sbph
+ # now we can check our remote sub repo
+```
diff --git a/doc/university/training/topics/tags.md b/doc/university/training/topics/tags.md
new file mode 100755
index 00000000000..e9607b5a875
--- /dev/null
+++ b/doc/university/training/topics/tags.md
@@ -0,0 +1,38 @@
+# Tags
+
+----------
+
+- Useful for marking deployments and releases
+- Annotated tags are an unchangeable part of Git history
+- Soft/lightweight tags can be set and removed at will
+- Many projects combine an anotated release tag with a stable branch
+- Consider setting deployment/release tags automatically
+
+----------
+
+# Tags
+
+- Create a lightweight tag
+- Create an annotated tag
+- Push the tags to the remote repository
+
+**Additional resources**
+
+[http://git-scm.com/book/en/Git-Basics-Tagging](http://git-scm.com/book/en/Git-Basics-Tagging)
+
+----------
+
+# Commands
+
+```
+git checkout master
+
+# Lightweight tag
+git tag my_lightweight_tag
+
+# Annotated tag
+git tag -a v1.0 -m ‘Version 1.0’
+git tag
+
+git push origin --tags
+```
diff --git a/doc/university/training/topics/unstage.md b/doc/university/training/topics/unstage.md
new file mode 100755
index 00000000000..17dbb64b9e6
--- /dev/null
+++ b/doc/university/training/topics/unstage.md
@@ -0,0 +1,31 @@
+# Unstage
+
+----------
+
+## Unstage
+
+* To remove files from stage use reset HEAD. Where HEAD is the last commit of the current branch.
+
+```bash
+git reset HEAD <file>
+```
+
+* This will unstage the file but maintain the modifications. To revert the file back to the state it was in before the changes we can use:
+
+```bash
+git checkout -- <file>
+```
+
+----------
+
+* To remove a file from disk and repo use 'git rm' and to rm a dir use the '-r' flag.
+```
+git rm '*.txt'
+git rm -r <dirname>
+```
+
+
+* If we want to remove a file from the repository but keep it on disk, say we forgot to add it to our `.gitignore` file then use `--cache`.
+```
+git rm <filename> --cache
+```
diff --git a/doc/university/training/user_training.md b/doc/university/training/user_training.md
new file mode 100755
index 00000000000..9e38df26b6a
--- /dev/null
+++ b/doc/university/training/user_training.md
@@ -0,0 +1,392 @@
+# GitLab Git Workshop
+
+---
+
+# Agenda
+
+1. Brief history of Git
+1. GitLab walkthrough
+1. Configure your environment
+1. Workshop
+
+---
+
+# Git introduction
+
+https://git-scm.com/about
+
+- Distributed version control
+ - Does not rely on connection to a central server
+ - Many copies of the complete history
+- Powerful branching and merging
+- Adapts to nearly any workflow
+- Fast, reliable and stable file format
+
+---
+
+# Help!
+
+Use the tools at your disposal when you get stuck.
+
+- Use '`git help <command>`' command
+- Use Google
+- Read documentation at https://git-scm.com
+
+---
+
+# GitLab Walkthrough
+
+![fit](logo.png)
+
+---
+
+# Configure your environment
+
+- Windows: Install 'Git for Windows'
+
+> https://git-for-windows.github.io
+
+- Mac: Type '`git`' in the Terminal application.
+
+> If it's not installed, it will prompt you to install it.
+
+- Debian: '`sudo apt-get install git-all`'
+or Red Hat '`sudo yum install git-all`'
+
+---
+
+# Git Workshop
+
+## Overview
+
+1. Configure Git
+1. Configure SSH Key
+1. Create a project
+1. Committing
+1. Feature branching
+1. Merge requests
+1. Feedback and Collaboration
+
+---
+
+# Configure Git
+
+One-time configuration of the Git client
+
+```bash
+git config --global user.name "Your Name"
+git config --global user.email you@example.com
+```
+
+---
+
+# Configure SSH Key
+
+```bash
+ssh-keygen -t rsa -b 4096 -C "you@computer-name"
+```
+
+```bash
+# You will be prompted for the following information. Press enter to accept the defaults. Defaults appear in parentheses.
+Generating public/private rsa key pair.
+Enter file in which to save the key (/Users/you/.ssh/id_rsa):
+Enter passphrase (empty for no passphrase):
+Enter same passphrase again:
+Your identification has been saved in /Users/you/.ssh/id_rsa.
+Your public key has been saved in /Users/you/.ssh/id_rsa.pub.
+The key fingerprint is:
+39:fc:ce:94:f4:09:13:95:64:9a:65:c1:de:05:4d:01 you@computer-name
+```
+
+Copy your public key and add it to your GitLab profile
+
+```bash
+cat ~/.ssh/id_rsa.pub
+```
+
+```bash
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQEL17Ufacg8cDhlQMS5NhV8z3GHZdhCrZbl4gz you@example.com
+```
+
+---
+
+# Create a project
+
+- Create a project in your user namespace
+ - Choose to import from 'Any Repo by URL' and use
+ https://gitlab.com/gitlab-org/training-examples.git
+- Create a '`development`' or '`workspace`' directory in your home directory.
+- Clone the '`training-examples`' project
+
+---
+
+# Commands
+
+```
+mkdir ~/development
+cd ~/development
+
+-or-
+
+mkdir ~/workspace
+cd ~/workspace
+
+git clone git@gitlab.example.com:<username>/training-examples.git
+cd training-examples
+```
+
+---
+
+# Git concepts
+
+**Untracked files**
+
+New files that Git has not been told to track previously.
+
+**Working area**
+
+Files that have been modified but are not committed.
+
+**Staging area**
+
+Modified files that have been marked to go in the next commit.
+
+---
+
+# Committing
+
+1. Edit '`edit_this_file.rb`' in '`training-examples`'
+1. See it listed as a changed file (working area)
+1. View the differences
+1. Stage the file
+1. Commit
+1. Push the commit to the remote
+1. View the git log
+
+---
+
+# Commands
+
+```
+# Edit `edit_this_file.rb`
+git status
+git diff
+git add <file>
+git commit -m 'My change'
+git push origin master
+git log
+```
+
+---
+
+# Feature branching
+
+- Efficient parallel workflow for teams
+- Develop each feature in a branch
+- Keeps changes isolated
+- Consider a 1-to-1 link to issues
+- Push branches to the server frequently
+ - Hint: This is a cheap backup for your work-in-progress code
+
+---
+
+# Feature branching
+
+1. Create a new feature branch called 'squash_some_bugs'
+1. Edit '`bugs.rb`' and remove all the bugs.
+1. Commit
+1. Push
+
+---
+
+# Commands
+
+```
+git checkout -b squash_some_bugs
+# Edit `bugs.rb`
+git status
+git add bugs.rb
+git commit -m 'Fix some buggy code'
+git push origin squash_some_bugs
+```
+
+---
+
+# Merge requests
+
+- When you want feedback create a merge request
+- Target is the ‘default’ branch (usually master)
+- Assign or mention the person you would like to review
+- Add 'WIP' to the title if it's a work in progress
+- When accepting, always delete the branch
+- Anyone can comment, not just the assignee
+- Push corrections to the same branch
+
+---
+
+# Merge requests
+
+**Create your first merge request**
+
+1. Use the blue button in the activity feed
+1. View the diff (changes) and leave a comment
+1. Push a new commit to the same branch
+1. Review the changes again and notice the update
+
+---
+
+# Feedback and Collaboration
+
+- Merge requests are a time for feedback and collaboration
+- Giving feedback is hard
+- Be as kind as possible
+- Receiving feedback is hard
+- Be as receptive as possible
+- Feedback is about the best code, not the person. You are not your code
+
+---
+
+# Feedback and Collaboration
+
+Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests:
+[https://github.com/thoughtbot/guides/tree/master/code-review](https://github.com/thoughtbot/guides/tree/master/code-review)
+
+See GitLab merge requests for examples:
+[https://gitlab.com/gitlab-org/gitlab-ce/merge_requests](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests)
+
+---
+
+# Explore GitLab projects
+
+![fit](logo.png)
+
+- Dashboard
+- User Preferences
+- ReadMe, Changelog, License shortcuts
+- Issues
+- Milestones and Labels
+- Manage project members
+- Project settings
+
+---
+
+# Tags
+
+- Useful for marking deployments and releases
+- Annotated tags are an unchangeable part of Git history
+- Soft/lightweight tags can be set and removed at will
+- Many projects combine an anotated release tag with a stable branch
+- Consider setting deployment/release tags automatically
+
+---
+
+# Tags
+
+- Create a lightweight tag
+- Create an annotated tag
+- Push the tags to the remote repository
+
+**Additional resources**
+
+[http://git-scm.com/book/en/Git-Basics-Tagging](http://git-scm.com/book/en/Git-Basics-Tagging)
+
+---
+
+# Commands
+
+```
+git checkout master
+
+# Lightweight tag
+git tag my_lightweight_tag
+
+# Annotated tag
+git tag -a v1.0 -m ‘Version 1.0’
+git tag
+
+git push origin --tags
+```
+
+---
+
+# Merge conflicts
+
+- Happen often
+- Learning to fix conflicts is hard
+- Practice makes perfect
+- Force push after fixing conflicts. Be careful!
+
+---
+
+# Merge conflicts
+
+1. Checkout a new branch and edit `conflicts.rb`. Add 'Line4' and 'Line5'.
+1. Commit and push
+1. Checkout master and edit `conflicts.rb`. Add 'Line6' and 'Line7' below 'Line3'.
+1. Commit and push to master
+1. Create a merge request
+
+---
+
+# Merge conflicts
+
+After creating a merge request you should notice that conflicts exist. Resolve
+the conflicts locally by rebasing.
+
+```
+git rebase master
+
+# Fix conflicts by editing the files.
+
+git add conflicts.rb
+git commit -m 'Fix conflicts'
+git rebase --continue
+git push origin <branch> -f
+```
+
+---
+
+# Rebase with squash
+
+You may end up with a commit log that looks like this:
+
+```
+Fix issue #13
+Test
+Fix
+Fix again
+Test
+Test again
+Does this work?
+```
+
+Squash these in to meaningful commits using an interactive rebase.
+
+---
+
+# Rebase with squash
+
+Squash the commits on the same branch we used for the merge conflicts step.
+
+```
+git rebase -i master
+```
+
+In the editor, leave the first commit as 'pick' and set others to 'fixup'.
+
+---
+
+# Questions?
+
+![fit](logo.png)
+
+Thank you for your hard work!
+
+**Additional Resources**
+
+GitLab Documentation [http://docs.gitlab.com](http://docs.gitlab.com/)
+GUI Clients [http://git-scm.com/downloads/guis](http://git-scm.com/downloads/guis)
+Pro git book [http://git-scm.com/book](http://git-scm.com/book)
+Platzi Course [https://courses.platzi.com/courses/git-gitlab/](https://courses.platzi.com/courses/git-gitlab/)
+Code School tutorial [http://try.github.io/](http://try.github.io/)
+Contact Us at `subscribers@gitlab.com`
diff --git a/doc/update/2.6-to-3.0.md b/doc/update/2.6-to-3.0.md
index fb70eaacbc9..97cd277b424 100644
--- a/doc/update/2.6-to-3.0.md
+++ b/doc/update/2.6-to-3.0.md
@@ -1,5 +1,5 @@
# From 2.6 to 3.0
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/2.6-to-3.0.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/2.6-to-3.0.md) for the most up to date instructions.*
## 1. Stop server & resque
diff --git a/doc/update/2.9-to-3.0.md b/doc/update/2.9-to-3.0.md
index ce46b57c09a..a890aa885d5 100644
--- a/doc/update/2.9-to-3.0.md
+++ b/doc/update/2.9-to-3.0.md
@@ -1,5 +1,5 @@
# From 2.9 to 3.0
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/2.9-to-3.0.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/2.9-to-3.0.md) for the most up to date instructions.*
## 1. Stop server & resque
diff --git a/doc/update/3.0-to-3.1.md b/doc/update/3.0-to-3.1.md
index 6ac83f3b60d..e32508745a2 100644
--- a/doc/update/3.0-to-3.1.md
+++ b/doc/update/3.0-to-3.1.md
@@ -1,5 +1,5 @@
# From 3.0 to 3.1
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/3.0-to-3.1.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/3.0-to-3.1.md) for the most up to date instructions.*
**IMPORTANT!**
diff --git a/doc/update/3.1-to-4.0.md b/doc/update/3.1-to-4.0.md
index df53ed6de83..b370464390e 100644
--- a/doc/update/3.1-to-4.0.md
+++ b/doc/update/3.1-to-4.0.md
@@ -1,5 +1,5 @@
# From 3.1 to 4.0
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/3.1-to-4.0.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/3.1-to-4.0.md) for the most up to date instructions.*
## Important changes
diff --git a/doc/update/4.0-to-4.1.md b/doc/update/4.0-to-4.1.md
index c66c6dd0fd8..7124424bb60 100644
--- a/doc/update/4.0-to-4.1.md
+++ b/doc/update/4.0-to-4.1.md
@@ -1,5 +1,5 @@
# From 4.0 to 4.1
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/4.0-to-4.1.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/4.0-to-4.1.md) for the most up to date instructions.*
## Important changes
diff --git a/doc/update/4.1-to-4.2.md b/doc/update/4.1-to-4.2.md
index 97367c5f347..8ed5b333a2e 100644
--- a/doc/update/4.1-to-4.2.md
+++ b/doc/update/4.1-to-4.2.md
@@ -1,5 +1,5 @@
# From 4.1 to 4.2
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/4.1-to-4.2.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/4.1-to-4.2.md) for the most up to date instructions.*
## 1. Stop server & Resque
diff --git a/doc/update/4.2-to-5.0.md b/doc/update/4.2-to-5.0.md
index 7654f4a0131..1ec39218ba8 100644
--- a/doc/update/4.2-to-5.0.md
+++ b/doc/update/4.2-to-5.0.md
@@ -1,5 +1,5 @@
# From 4.2 to 5.0
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/4.2-to-5.0.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/4.2-to-5.0.md) for the most up to date instructions.*
## Warning
diff --git a/doc/update/5.0-to-5.1.md b/doc/update/5.0-to-5.1.md
index c19a819ab5a..9c9950fb2c6 100644
--- a/doc/update/5.0-to-5.1.md
+++ b/doc/update/5.0-to-5.1.md
@@ -1,5 +1,5 @@
# From 5.0 to 5.1
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/5.0-to-5.1.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.0-to-5.1.md) for the most up to date instructions.*
## Warning
diff --git a/doc/update/5.1-to-5.2.md b/doc/update/5.1-to-5.2.md
index 625fcc33852..2aab47d2d7c 100644
--- a/doc/update/5.1-to-5.2.md
+++ b/doc/update/5.1-to-5.2.md
@@ -1,5 +1,5 @@
# From 5.1 to 5.2
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/5.1-to-5.2.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.1-to-5.2.md) for the most up to date instructions.*
## Warning
diff --git a/doc/update/5.1-to-5.4.md b/doc/update/5.1-to-5.4.md
index 547d453914c..e80f1b89c63 100644
--- a/doc/update/5.1-to-5.4.md
+++ b/doc/update/5.1-to-5.4.md
@@ -1,5 +1,5 @@
# From 5.1 to 5.4
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/5.1-to-5.4.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.1-to-5.4.md) for the most up to date instructions.*
Also works starting from 5.2.
diff --git a/doc/update/5.1-to-6.0.md b/doc/update/5.1-to-6.0.md
index c992c69678e..1ee175383da 100644
--- a/doc/update/5.1-to-6.0.md
+++ b/doc/update/5.1-to-6.0.md
@@ -1,5 +1,5 @@
# From 5.1 to 6.0
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/5.1-to-6.0.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.1-to-6.0.md) for the most up to date instructions.*
## Warning
diff --git a/doc/update/5.2-to-5.3.md b/doc/update/5.2-to-5.3.md
index fe8990b6843..2ae50510f63 100644
--- a/doc/update/5.2-to-5.3.md
+++ b/doc/update/5.2-to-5.3.md
@@ -1,5 +1,5 @@
# From 5.2 to 5.3
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/5.2-to-5.3.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.2-to-5.3.md) for the most up to date instructions.*
## Warning
diff --git a/doc/update/5.3-to-5.4.md b/doc/update/5.3-to-5.4.md
index 5f82ad7d444..842e3bb6791 100644
--- a/doc/update/5.3-to-5.4.md
+++ b/doc/update/5.3-to-5.4.md
@@ -1,5 +1,5 @@
# From 5.3 to 5.4
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/5.3-to-5.4.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.3-to-5.4.md) for the most up to date instructions.*
## 0. Backup
diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md
index f0fee634322..44715984f0c 100644
--- a/doc/update/5.4-to-6.0.md
+++ b/doc/update/5.4-to-6.0.md
@@ -1,5 +1,5 @@
# From 5.4 to 6.0
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/5.4-to-6.0.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/5.4-to-6.0.md) for the most up to date instructions.*
## Warning
diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md
index 409faf30902..0c672abeb05 100644
--- a/doc/update/6.0-to-6.1.md
+++ b/doc/update/6.0-to-6.1.md
@@ -1,5 +1,5 @@
# From 6.0 to 6.1
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.0-to-6.1.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.0-to-6.1.md) for the most up to date instructions.*
## Warning
diff --git a/doc/update/6.1-to-6.2.md b/doc/update/6.1-to-6.2.md
index 150c7ae1c83..d3760cf0619 100644
--- a/doc/update/6.1-to-6.2.md
+++ b/doc/update/6.1-to-6.2.md
@@ -1,5 +1,5 @@
# From 6.1 to 6.2
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.1-to-6.2.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.1-to-6.2.md) for the most up to date instructions.*
**You should update to 6.1 before installing 6.2 so all the necessary conversions are run.**
diff --git a/doc/update/6.2-to-6.3.md b/doc/update/6.2-to-6.3.md
index b96dfb8add7..91105de2e29 100644
--- a/doc/update/6.2-to-6.3.md
+++ b/doc/update/6.2-to-6.3.md
@@ -1,5 +1,5 @@
# From 6.2 to 6.3
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.2-to-6.3.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.2-to-6.3.md) for the most up to date instructions.*
**Requires version: 6.1 or 6.2.**
diff --git a/doc/update/6.3-to-6.4.md b/doc/update/6.3-to-6.4.md
index 37028be055f..20b58ed8b25 100644
--- a/doc/update/6.3-to-6.4.md
+++ b/doc/update/6.3-to-6.4.md
@@ -1,5 +1,5 @@
# From 6.3 to 6.4
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.3-to-6.4.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.3-to-6.4.md) for the most up to date instructions.*
## 0. Backup
diff --git a/doc/update/6.4-to-6.5.md b/doc/update/6.4-to-6.5.md
index 982381a4db0..5ee0f040b5d 100644
--- a/doc/update/6.4-to-6.5.md
+++ b/doc/update/6.4-to-6.5.md
@@ -1,5 +1,5 @@
# From 6.4 to 6.5
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.4-to-6.5.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.4-to-6.5.md) for the most up to date instructions.*
## 0. Backup
diff --git a/doc/update/6.5-to-6.6.md b/doc/update/6.5-to-6.6.md
index bbed2b30215..fa3712f83ad 100644
--- a/doc/update/6.5-to-6.6.md
+++ b/doc/update/6.5-to-6.6.md
@@ -1,5 +1,5 @@
# From 6.5 to 6.6
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.5-to-6.6.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.5-to-6.6.md) for the most up to date instructions.*
## 0. Backup
diff --git a/doc/update/6.6-to-6.7.md b/doc/update/6.6-to-6.7.md
index 8e82942a1a0..9c85ed091c5 100644
--- a/doc/update/6.6-to-6.7.md
+++ b/doc/update/6.6-to-6.7.md
@@ -1,5 +1,5 @@
# From 6.6 to 6.7
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.6-to-6.7.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.6-to-6.7.md) for the most up to date instructions.*
## 0. Backup
diff --git a/doc/update/6.7-to-6.8.md b/doc/update/6.7-to-6.8.md
index 4fb90639f16..687c1265d9b 100644
--- a/doc/update/6.7-to-6.8.md
+++ b/doc/update/6.7-to-6.8.md
@@ -1,5 +1,5 @@
# From 6.7 to 6.8
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.7-to-6.8.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.7-to-6.8.md) for the most up to date instructions.*
## 0. Backup
diff --git a/doc/update/6.8-to-6.9.md b/doc/update/6.8-to-6.9.md
index b9b8b63f652..0205b0c896a 100644
--- a/doc/update/6.8-to-6.9.md
+++ b/doc/update/6.8-to-6.9.md
@@ -1,5 +1,5 @@
# From 6.8 to 6.9
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.8-to-6.9.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.8-to-6.9.md) for the most up to date instructions.*
### 0. Backup
diff --git a/doc/update/6.9-to-7.0.md b/doc/update/6.9-to-7.0.md
index 5352fd52f93..4b6e3989893 100644
--- a/doc/update/6.9-to-7.0.md
+++ b/doc/update/6.9-to-7.0.md
@@ -1,5 +1,5 @@
# From 6.9 to 7.0
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.9-to-7.0.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.9-to-7.0.md) for the most up to date instructions.*
### 0. Backup
diff --git a/doc/update/6.x-or-7.x-to-7.14.md b/doc/update/6.x-or-7.x-to-7.14.md
index f170a0021b7..1e39fe47ef9 100644
--- a/doc/update/6.x-or-7.x-to-7.14.md
+++ b/doc/update/6.x-or-7.x-to-7.14.md
@@ -1,5 +1,5 @@
# From 6.x or 7.x to 7.14
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/6.x-or-7.x-to-7.14.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/6.x-or-7.x-to-7.14.md) for the most up to date instructions.*
This allows you to upgrade any version of GitLab from 6.0 and up (including 7.0 and up) to 7.14.
@@ -222,7 +222,7 @@ If all items are green, then congratulations upgrade complete!
When using Google omniauth login, changes of the Google account required.
Ensure that `Contacts API` and the `Google+ API` are enabled in the [Google Developers Console](https://console.developers.google.com/).
-More details can be found at the [integration documentation](../../../master/doc/integration/google.md).
+More details can be found at the [integration documentation](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/integration/google.md).
## 12. Optional optimizations for GitLab setups with MySQL databases
diff --git a/doc/update/7.0-to-7.1.md b/doc/update/7.0-to-7.1.md
index 71f39c44077..2e9457aa142 100644
--- a/doc/update/7.0-to-7.1.md
+++ b/doc/update/7.0-to-7.1.md
@@ -1,5 +1,5 @@
# From 7.0 to 7.1
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/7.0-to-7.1.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/7.0-to-7.1.md) for the most up to date instructions.*
### 0. Backup
@@ -136,3 +136,5 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-1-stable/config/gitlab.yml.example
diff --git a/doc/update/7.1-to-7.2.md b/doc/update/7.1-to-7.2.md
index 88cb63d7d41..e5045b5570f 100644
--- a/doc/update/7.1-to-7.2.md
+++ b/doc/update/7.1-to-7.2.md
@@ -1,5 +1,5 @@
# From 7.1 to 7.2
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/7.1-to-7.2.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/7.1-to-7.2.md) for the most up to date instructions.*
## Editable labels
@@ -135,3 +135,5 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-2-stable/config/gitlab.yml.example
diff --git a/doc/update/7.10-to-7.11.md b/doc/update/7.10-to-7.11.md
index 79bc6de1e46..89213ba7178 100644
--- a/doc/update/7.10-to-7.11.md
+++ b/doc/update/7.10-to-7.11.md
@@ -65,7 +65,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`.
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
```
git diff origin/7-10-stable:config/gitlab.yml.example origin/7-11-stable:config/gitlab.yml.example
@@ -101,3 +101,5 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-11-stable/config/gitlab.yml.example
diff --git a/doc/update/7.11-to-7.12.md b/doc/update/7.11-to-7.12.md
index cc14a135926..3865186918c 100644
--- a/doc/update/7.11-to-7.12.md
+++ b/doc/update/7.11-to-7.12.md
@@ -91,7 +91,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`.
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
```
git diff origin/7-11-stable:config/gitlab.yml.example origin/7-12-stable:config/gitlab.yml.example
@@ -127,3 +127,5 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-12-stable/config/gitlab.yml.example
diff --git a/doc/update/7.12-to-7.13.md b/doc/update/7.12-to-7.13.md
index 57ebe3261b6..4c8d8f1f741 100644
--- a/doc/update/7.12-to-7.13.md
+++ b/doc/update/7.12-to-7.13.md
@@ -91,7 +91,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`.
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
```
git diff origin/7-12-stable:config/gitlab.yml.example origin/7-13-stable:config/gitlab.yml.example
@@ -127,3 +127,5 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-13-stable/config/gitlab.yml.example
diff --git a/doc/update/7.13-to-7.14.md b/doc/update/7.13-to-7.14.md
index 6dd9727fb49..934898da5a1 100644
--- a/doc/update/7.13-to-7.14.md
+++ b/doc/update/7.13-to-7.14.md
@@ -91,7 +91,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`.
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
```
git diff origin/7-13-stable:config/gitlab.yml.example origin/7-14-stable:config/gitlab.yml.example
@@ -127,3 +127,5 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-14-stable/config/gitlab.yml.example
diff --git a/doc/update/7.14-to-8.0.md b/doc/update/7.14-to-8.0.md
index 117e2afaaa0..25fa6d93f06 100644
--- a/doc/update/7.14-to-8.0.md
+++ b/doc/update/7.14-to-8.0.md
@@ -143,7 +143,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/7-14-stable:config/gitlab.yml.example origin/8-0-stable:config/gitlab.yml.example
@@ -227,3 +227,5 @@ this is likely due to an outdated Nginx or Apache configuration, or a missing or
misconfigured `gitlab-git-http-server` instance. Double-check that you correctly
completed [Step 5](#5-install-gitlab-git-http-server) to install the daemon and
[Step 8](#new-nginx-configuration) to reconfigure Nginx.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-0-stable/config/gitlab.yml.example
diff --git a/doc/update/7.2-to-7.3.md b/doc/update/7.2-to-7.3.md
index 18f77d6396e..d3391ddd225 100644
--- a/doc/update/7.2-to-7.3.md
+++ b/doc/update/7.2-to-7.3.md
@@ -1,5 +1,5 @@
# From 7.2 to 7.3
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/7.2-to-7.3.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/7.2-to-7.3.md) for the most up to date instructions.*
### 0. Backup
@@ -143,3 +143,5 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-3-stable/config/gitlab.yml.example
diff --git a/doc/update/7.3-to-7.4.md b/doc/update/7.3-to-7.4.md
index 53e739c06fb..6d632dc3c8e 100644
--- a/doc/update/7.3-to-7.4.md
+++ b/doc/update/7.3-to-7.4.md
@@ -1,5 +1,5 @@
# From 7.3 to 7.4
-*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/7.3-to-7.4.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update/7.3-to-7.4.md) for the most up to date instructions.*
### 0. Stop server
@@ -75,7 +75,7 @@ sudo -u git -H editor config/unicorn.rb
#### MySQL Databases: Update database.yml config file
-* Add `collation: utf8_general_ci` to `config/database.yml` as seen in [config/database.yml.mysql](/config/database.yml.mysql)
+* Add `collation: utf8_general_ci` to `config/database.yml` as seen in [config/database.yml.mysql][mysql]:
```
sudo -u git -H editor config/database.yml
@@ -192,6 +192,5 @@ sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-
-
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/config/gitlab.yml.example
+[mysql]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/config/database.yml.mysql
diff --git a/doc/update/7.4-to-7.5.md b/doc/update/7.4-to-7.5.md
index 673eab3c56e..ec50706d421 100644
--- a/doc/update/7.4-to-7.5.md
+++ b/doc/update/7.4-to-7.5.md
@@ -73,8 +73,8 @@ git diff origin/7-4-stable:config/gitlab.yml.example origin/7-5-stable:config/gi
#### Change Nginx settings
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your setting
+* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`][nginx] but with your settings
+* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your setting
### 6. Start application
@@ -106,3 +106,7 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-5-stable/config/gitlab.yml.example
+[nginx]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-5-stable/lib/support/nginx/gitlab
+[nginx-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-5-stable/lib/support/nginx/gitlab-ssl
diff --git a/doc/update/7.5-to-7.6.md b/doc/update/7.5-to-7.6.md
index 35cd437fdc4..331f5de080e 100644
--- a/doc/update/7.5-to-7.6.md
+++ b/doc/update/7.5-to-7.6.md
@@ -67,7 +67,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`.
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
```
git diff origin/7-5-stable:config/gitlab.yml.example origin/7-6-stable:config/gitlab.yml.example
@@ -75,12 +75,12 @@ git diff origin/7-5-stable:config/gitlab.yml.example origin/7-6-stable:config/gi
#### Change Nginx settings
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your setting
+* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`][nginx] but with your settings
+* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your setting
#### Setup time zone (optional)
-Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`](config/application.rb) (unlikely), unset it.
+Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
### 6. Start application
@@ -112,3 +112,8 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-6-stable/config/gitlab.yml.example
+[app]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-6-stable/config/application.rb
+[nginx]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-6-stable/lib/support/nginx/gitlab
+[nginx-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-6-stable/lib/support/nginx/gitlab-ssl
diff --git a/doc/update/7.6-to-7.7.md b/doc/update/7.6-to-7.7.md
index 910c7dcdd3c..918b10fbd95 100644
--- a/doc/update/7.6-to-7.7.md
+++ b/doc/update/7.6-to-7.7.md
@@ -67,7 +67,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](/config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`.
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
```
git diff origin/7-6-stable:config/gitlab.yml.example origin/7-7-stable:config/gitlab.yml.example
@@ -75,12 +75,12 @@ git diff origin/7-6-stable:config/gitlab.yml.example origin/7-7-stable:config/gi
#### Change Nginx settings
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your setting
+* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`][nginx] but with your settings
+* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your setting
#### Setup time zone (optional)
-Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`](config/application.rb) (unlikely), unset it.
+Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
### 6. Start application
@@ -101,7 +101,7 @@ If all items are green, then congratulations upgrade is complete!
### 8. GitHub settings (if applicable)
-If you are using GitHub as an OAuth provider for authentication, you should change the callback URL so that it
+If you are using GitHub as an OAuth provider for authentication, you should change the callback URL so that it
only contains a root URL (ex. `https://gitlab.example.com/`)
## Things went south? Revert to previous version (7.6)
@@ -117,3 +117,8 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-7-stable/config/gitlab.yml.example
+[app]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-7-stable/config/application.rb
+[nginx]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-7-stable/lib/support/nginx/gitlab
+[nginx-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-7-stable/lib/support/nginx/gitlab-ssl
diff --git a/doc/update/7.7-to-7.8.md b/doc/update/7.7-to-7.8.md
index 46ca163c1bb..84e0464a824 100644
--- a/doc/update/7.7-to-7.8.md
+++ b/doc/update/7.7-to-7.8.md
@@ -67,7 +67,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`.
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
```
git diff origin/7-7-stable:config/gitlab.yml.example origin/7-8-stable:config/gitlab.yml.example
@@ -75,13 +75,13 @@ git diff origin/7-7-stable:config/gitlab.yml.example origin/7-8-stable:config/gi
#### Change Nginx settings
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings.
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your settings.
+* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`][nginx] but with your settings.
+* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your settings.
* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
#### Setup time zone (optional)
-Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`](config/application.rb) (unlikely), unset it.
+Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
### 6. Start application
@@ -118,3 +118,8 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/config/gitlab.yml.example
+[app]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/config/application.rb
+[nginx]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/lib/support/nginx/gitlab
+[nginx-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-8-stable/lib/support/nginx/gitlab-ssl
diff --git a/doc/update/7.8-to-7.9.md b/doc/update/7.8-to-7.9.md
index 6ffa21c6141..b0dc2ba1dbb 100644
--- a/doc/update/7.8-to-7.9.md
+++ b/doc/update/7.8-to-7.9.md
@@ -69,7 +69,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`.
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
```
git diff origin/7-8-stable:config/gitlab.yml.example origin/7-9-stable:config/gitlab.yml.example
@@ -77,13 +77,13 @@ git diff origin/7-8-stable:config/gitlab.yml.example origin/7-9-stable:config/gi
#### Change Nginx settings
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings.
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your settings.
+* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`][nginx] but with your settings.
+* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your settings.
* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
#### Setup time zone (optional)
-Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`](config/application.rb) (unlikely), unset it.
+Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
### 6. Start application
@@ -120,3 +120,8 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-9-stable/config/gitlab.yml.example
+[app]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-9-stable/config/application.rb
+[nginx]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-9-stable/lib/support/nginx/gitlab
+[nginx-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-9-stable/lib/support/nginx/gitlab-ssl
diff --git a/doc/update/7.9-to-7.10.md b/doc/update/7.9-to-7.10.md
index d1179dc2ec7..8f7f84b41ba 100644
--- a/doc/update/7.9-to-7.10.md
+++ b/doc/update/7.9-to-7.10.md
@@ -65,7 +65,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them to your current `gitlab.yml`.
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them to your current `gitlab.yml`.
```
git diff origin/7-9-stable:config/gitlab.yml.example origin/7-10-stable:config/gitlab.yml.example
@@ -73,13 +73,13 @@ git diff origin/7-9-stable:config/gitlab.yml.example origin/7-10-stable:config/g
#### Change Nginx settings
-* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`](/lib/support/nginx/gitlab) but with your settings.
-* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`](/lib/support/nginx/gitlab-ssl) but with your settings.
+* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`][nginx] but with your settings.
+* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your settings.
* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
#### Setup time zone (optional)
-Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`](config/application.rb) (unlikely), unset it.
+Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
### 6. Start application
@@ -116,3 +116,8 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-10-stable/config/gitlab.yml.example
+[app]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-10-stable/config/application.rb
+[nginx]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-10-stable/lib/support/nginx/gitlab
+[nginx-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/7-10-stable/lib/support/nginx/gitlab-ssl
diff --git a/doc/update/8.0-to-8.1.md b/doc/update/8.0-to-8.1.md
index bfb83cf79b1..6ee0c0656ee 100644
--- a/doc/update/8.0-to-8.1.md
+++ b/doc/update/8.0-to-8.1.md
@@ -108,7 +108,7 @@ For Ubuntu 16.04.1 LTS:
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/8-0-stable:config/gitlab.yml.example origin/8-1-stable:config/gitlab.yml.example
@@ -173,3 +173,5 @@ If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of
### "You appear to have cloned an empty repository."
See the [7.14 to 8.0 update guide](7.14-to-8.0.md#troubleshooting).
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-1-stable/config/gitlab.yml.example
diff --git a/doc/update/8.1-to-8.2.md b/doc/update/8.1-to-8.2.md
index 7f36ce00e96..4c9ff5c5c0a 100644
--- a/doc/update/8.1-to-8.2.md
+++ b/doc/update/8.1-to-8.2.md
@@ -125,7 +125,7 @@ For Ubuntu 16.04.1 LTS:
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/8-1-stable:config/gitlab.yml.example origin/8-2-stable:config/gitlab.yml.example
@@ -190,3 +190,5 @@ If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of
### "You appear to have cloned an empty repository."
See the [7.14 to 8.0 update guide](7.14-to-8.0.md#troubleshooting).
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-2-stable/config/gitlab.yml.example
diff --git a/doc/update/8.10-to-8.11.md b/doc/update/8.10-to-8.11.md
index 119c5f475e4..e538983e603 100644
--- a/doc/update/8.10-to-8.11.md
+++ b/doc/update/8.10-to-8.11.md
@@ -49,6 +49,8 @@ sudo gem install bundler --no-ri --no-rdoc
### 4. Get latest code
```bash
+cd /home/git/gitlab
+
sudo -u git -H git fetch --all
sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
```
@@ -114,7 +116,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/8-10-stable:config/gitlab.yml.example origin/8-11-stable:config/gitlab.yml.example
@@ -195,3 +197,5 @@ sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-11-stable/config/gitlab.yml.example
diff --git a/doc/update/8.11-to-8.12.md b/doc/update/8.11-to-8.12.md
index 07743d050f7..604166beb56 100644
--- a/doc/update/8.11-to-8.12.md
+++ b/doc/update/8.11-to-8.12.md
@@ -49,6 +49,8 @@ sudo gem install bundler --no-ri --no-rdoc
### 4. Get latest code
```bash
+cd /home/git/gitlab
+
sudo -u git -H git fetch --all
sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
```
@@ -72,7 +74,7 @@ sudo -u git -H git checkout 8-12-stable-ee
```bash
cd /home/git/gitlab-shell
sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v3.6.0
+sudo -u git -H git checkout v3.6.1
```
### 6. Update gitlab-workhorse
@@ -113,7 +115,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/8-11-stable:config/gitlab.yml.example origin/8-12-stable:config/gitlab.yml.example
@@ -203,3 +205,5 @@ sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-12-stable/config/gitlab.yml.example
diff --git a/doc/update/8.12-to-8.13.md b/doc/update/8.12-to-8.13.md
index 00d63c1b3c6..d83965131f5 100644
--- a/doc/update/8.12-to-8.13.md
+++ b/doc/update/8.12-to-8.13.md
@@ -49,6 +49,8 @@ sudo gem install bundler --no-ri --no-rdoc
### 4. Get latest code
```bash
+cd /home/git/gitlab
+
sudo -u git -H git fetch --all
sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
```
@@ -72,7 +74,7 @@ sudo -u git -H git checkout 8-13-stable-ee
```bash
cd /home/git/gitlab-shell
sudo -u git -H git fetch --all --tags
-sudo -u git -H git checkout v3.6.3
+sudo -u git -H git checkout v3.6.7
```
### 6. Update gitlab-workhorse
@@ -84,7 +86,7 @@ GitLab 8.1.
```bash
cd /home/git/gitlab-workhorse
sudo -u git -H git fetch --all
-sudo -u git -H git checkout v0.8.4
+sudo -u git -H git checkout v0.8.5
sudo -u git -H make
```
@@ -113,7 +115,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/8-12-stable:config/gitlab.yml.example origin/8-13-stable:config/gitlab.yml.example
@@ -166,7 +168,7 @@ See [smtp_settings.rb.sample] as an example.
Ensure you're still up-to-date with the latest init script changes:
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
+
For Ubuntu 16.04.1 LTS:
sudo systemctl daemon-reload
@@ -203,3 +205,5 @@ sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-13-stable/config/gitlab.yml.example
diff --git a/doc/update/8.13-to-8.14.md b/doc/update/8.13-to-8.14.md
new file mode 100644
index 00000000000..aaadcec8ac0
--- /dev/null
+++ b/doc/update/8.13-to-8.14.md
@@ -0,0 +1,209 @@
+# From 8.13 to 8.14
+
+Make sure you view this update guide from the tag (version) of GitLab you would
+like to install. In most cases this should be the highest numbered production
+tag (without rc in it). You can select the tag in the version dropdown at the
+top left corner of GitLab (below the menu bar).
+
+If the highest number stable branch is unclear please check the
+[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
+guide links by version.
+
+### 1. Stop server
+
+ sudo service gitlab stop
+
+### 2. Backup
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 3. Update Ruby
+
+We will continue supporting Ruby < 2.3 for the time being but we recommend you
+upgrade to Ruby 2.3 if you're running a source installation, as this is the same
+version that ships with our Omnibus package.
+
+You can check which version you are running with `ruby -v`.
+
+Download and compile Ruby:
+
+```bash
+mkdir /tmp/ruby && cd /tmp/ruby
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz
+echo 'c39b4001f7acb4e334cb60a0f4df72d434bef711 ruby-2.3.1.tar.gz' | shasum --check - && tar xzf ruby-2.3.1.tar.gz
+cd ruby-2.3.1
+./configure --disable-install-rdoc
+make
+sudo make install
+```
+
+Install Bundler:
+
+```bash
+sudo gem install bundler --no-ri --no-rdoc
+```
+
+### 4. Get latest code
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+sudo -u git -H git checkout 8-14-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+sudo -u git -H git checkout 8-14-stable-ee
+```
+
+### 5. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v4.1.1
+```
+
+### 6. Update gitlab-workhorse
+
+Install and compile gitlab-workhorse. This requires
+[Go 1.5](https://golang.org/dl) which should already be on your system from
+GitLab 8.1.
+
+```bash
+cd /home/git/gitlab-workhorse
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout v1.0.1
+sudo -u git -H make
+```
+
+### 7. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without postgres')
+sudo -u git -H bundle install --without postgres development test --deployment
+
+# PostgreSQL installations (note: the line below states '--without mysql')
+sudo -u git -H bundle install --without mysql development test --deployment
+
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Clean up assets and cache
+sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
+```
+
+### 8. Update configuration files
+
+#### New configuration options for `gitlab.yml`
+
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+git diff origin/8-13-stable:config/gitlab.yml.example origin/8-14-stable:config/gitlab.yml.example
+```
+
+#### Git configuration
+
+Configure Git to generate packfile bitmaps (introduced in Git 2.0) on
+the GitLab server during `git gc`.
+
+```sh
+sudo -u git -H git config --global repack.writeBitmaps true
+```
+
+#### Nginx configuration
+
+Ensure you're still up-to-date with the latest NGINX configuration changes:
+
+```sh
+# For HTTPS configurations
+git diff origin/8-13-stable:lib/support/nginx/gitlab-ssl origin/8-14-stable:lib/support/nginx/gitlab-ssl
+
+# For HTTP configurations
+git diff origin/8-13-stable:lib/support/nginx/gitlab origin/8-14-stable:lib/support/nginx/gitlab
+```
+
+If you are using Apache instead of NGINX please see the updated [Apache templates].
+Also note that because Apache does not support upstreams behind Unix sockets you
+will need to let gitlab-workhorse listen on a TCP port. You can do this
+via [/etc/default/gitlab].
+
+[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
+[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-14-stable/lib/support/init.d/gitlab.default.example#L38
+
+#### SMTP configuration
+
+If you're installing from source and use SMTP to deliver mail, you will need to add the following line
+to config/initializers/smtp_settings.rb:
+
+```ruby
+ActionMailer::Base.delivery_method = :smtp
+```
+
+See [smtp_settings.rb.sample] as an example.
+
+[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-14-stable/config/initializers/smtp_settings.rb.sample#L13
+
+#### Init script
+
+Ensure you're still up-to-date with the latest init script changes:
+
+ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+
+For Ubuntu 16.04.1 LTS:
+
+ sudo systemctl daemon-reload
+
+### 9. Start application
+
+ sudo service gitlab start
+ sudo service nginx restart
+
+### 10. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+ sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+
+To make sure you didn't miss anything run a more thorough check:
+
+ sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+
+If all items are green, then congratulations, the upgrade is complete!
+
+## Things went south? Revert to previous version (8.13)
+
+### 1. Revert the code to the previous version
+
+Follow the [upgrade guide from 8.12 to 8.13](8.12-to-8.13.md), except for the
+database migration (the backup is already migrated to the previous version).
+
+### 2. Restore from the backup
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
+If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-14-stable/config/gitlab.yml.example
diff --git a/doc/update/8.14-to-8.15.md b/doc/update/8.14-to-8.15.md
new file mode 100644
index 00000000000..a68fe3bb605
--- /dev/null
+++ b/doc/update/8.14-to-8.15.md
@@ -0,0 +1,239 @@
+# From 8.14 to 8.15
+
+Make sure you view this update guide from the tag (version) of GitLab you would
+like to install. In most cases this should be the highest numbered production
+tag (without rc in it). You can select the tag in the version dropdown at the
+top left corner of GitLab (below the menu bar).
+
+If the highest number stable branch is unclear please check the
+[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
+guide links by version.
+
+### 1. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
+### 2. Backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 3. Update Ruby
+
+We will continue supporting Ruby < 2.3 for the time being but we recommend you
+upgrade to Ruby 2.3 if you're running a source installation, as this is the same
+version that ships with our Omnibus package.
+
+You can check which version you are running with `ruby -v`.
+
+Download and compile Ruby:
+
+```bash
+mkdir /tmp/ruby && cd /tmp/ruby
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz
+echo 'c39b4001f7acb4e334cb60a0f4df72d434bef711 ruby-2.3.1.tar.gz' | shasum --check - && tar xzf ruby-2.3.1.tar.gz
+cd ruby-2.3.1
+./configure --disable-install-rdoc
+make
+sudo make install
+```
+
+Install Bundler:
+
+```bash
+sudo gem install bundler --no-ri --no-rdoc
+```
+
+### 4. Get latest code
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 8-15-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 8-15-stable-ee
+```
+
+### 5. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without postgres')
+sudo -u git -H bundle install --without postgres development test --deployment
+
+# PostgreSQL installations (note: the line below states '--without mysql')
+sudo -u git -H bundle install --without mysql development test --deployment
+
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Clean up assets and cache
+sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
+```
+
+### 6. Update gitlab-workhorse
+
+Install and compile gitlab-workhorse. This requires
+[Go 1.5](https://golang.org/dl) which should already be on your system from
+GitLab 8.1.
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production
+```
+
+### 7. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v4.1.1
+```
+
+### 8. Update configuration files
+
+#### New configuration options for `gitlab.yml`
+
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/8-14-stable:config/gitlab.yml.example origin/8-15-stable:config/gitlab.yml.example
+```
+
+#### Git configuration
+
+Configure Git to generate packfile bitmaps (introduced in Git 2.0) on
+the GitLab server during `git gc`.
+
+```sh
+cd /home/git/gitlab
+
+sudo -u git -H git config --global repack.writeBitmaps true
+```
+
+#### Nginx configuration
+
+Ensure you're still up-to-date with the latest NGINX configuration changes:
+
+```sh
+cd /home/git/gitlab
+
+# For HTTPS configurations
+git diff origin/8-14-stable:lib/support/nginx/gitlab-ssl origin/8-15-stable:lib/support/nginx/gitlab-ssl
+
+# For HTTP configurations
+git diff origin/8-14-stable:lib/support/nginx/gitlab origin/8-15-stable:lib/support/nginx/gitlab
+```
+
+If you are using Apache instead of NGINX please see the updated [Apache templates].
+Also note that because Apache does not support upstreams behind Unix sockets you
+will need to let gitlab-workhorse listen on a TCP port. You can do this
+via [/etc/default/gitlab].
+
+[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
+[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-15-stable/lib/support/init.d/gitlab.default.example#L38
+
+#### SMTP configuration
+
+If you're installing from source and use SMTP to deliver mail, you will need to add the following line
+to config/initializers/smtp_settings.rb:
+
+```ruby
+ActionMailer::Base.delivery_method = :smtp
+```
+
+See [smtp_settings.rb.sample] as an example.
+
+[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-15-stable/config/initializers/smtp_settings.rb.sample#L13
+
+#### Init script
+
+Ensure you're still up-to-date with the latest init script changes:
+
+```bash
+cd /home/git/gitlab
+
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+For Ubuntu 16.04.1 LTS:
+
+```bash
+sudo systemctl daemon-reload
+```
+
+### 9. Start application
+
+```bash
+sudo service gitlab start
+sudo service nginx restart
+```
+
+### 10. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+```
+
+To make sure you didn't miss anything run a more thorough check:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```
+
+If all items are green, then congratulations, the upgrade is complete!
+
+## Things went south? Revert to previous version (8.14)
+
+### 1. Revert the code to the previous version
+
+Follow the [upgrade guide from 8.13 to 8.14](8.13-to-8.14.md), except for the
+database migration (the backup is already migrated to the previous version).
+
+### 2. Restore from the backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
+If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-15-stable/config/gitlab.yml.example
diff --git a/doc/update/8.15-to-8.16.md b/doc/update/8.15-to-8.16.md
new file mode 100644
index 00000000000..9f8f0f714d4
--- /dev/null
+++ b/doc/update/8.15-to-8.16.md
@@ -0,0 +1,241 @@
+# From 8.15 to 8.16
+
+Make sure you view this update guide from the tag (version) of GitLab you would
+like to install. In most cases this should be the highest numbered production
+tag (without rc in it). You can select the tag in the version dropdown at the
+top left corner of GitLab (below the menu bar).
+
+If the highest number stable branch is unclear please check the
+[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
+guide links by version.
+
+### 1. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
+### 2. Backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 3. Update Ruby
+
+We will continue supporting Ruby < 2.3 for the time being but we recommend you
+upgrade to Ruby 2.3 if you're running a source installation, as this is the same
+version that ships with our Omnibus package.
+
+You can check which version you are running with `ruby -v`.
+
+Download and compile Ruby:
+
+```bash
+mkdir /tmp/ruby && cd /tmp/ruby
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
+echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
+cd ruby-2.3.3
+./configure --disable-install-rdoc
+make
+sudo make install
+```
+
+Install Bundler:
+
+```bash
+sudo gem install bundler --no-ri --no-rdoc
+```
+
+### 4. Get latest code
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 8-16-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 8-16-stable-ee
+```
+
+### 5. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without postgres')
+sudo -u git -H bundle install --without postgres development test --deployment
+
+# PostgreSQL installations (note: the line below states '--without mysql')
+sudo -u git -H bundle install --without mysql development test --deployment
+
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Clean up assets and cache
+sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
+```
+
+**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
+
+### 6. Update gitlab-workhorse
+
+Install and compile gitlab-workhorse. This requires
+[Go 1.5](https://golang.org/dl) which should already be on your system from
+GitLab 8.1.
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production
+```
+
+### 7. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v4.1.1
+```
+
+### 8. Update configuration files
+
+#### New configuration options for `gitlab.yml`
+
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/8-15-stable:config/gitlab.yml.example origin/8-16-stable:config/gitlab.yml.example
+```
+
+#### Git configuration
+
+Configure Git to generate packfile bitmaps (introduced in Git 2.0) on
+the GitLab server during `git gc`.
+
+```sh
+cd /home/git/gitlab
+
+sudo -u git -H git config --global repack.writeBitmaps true
+```
+
+#### Nginx configuration
+
+Ensure you're still up-to-date with the latest NGINX configuration changes:
+
+```sh
+cd /home/git/gitlab
+
+# For HTTPS configurations
+git diff origin/8-15-stable:lib/support/nginx/gitlab-ssl origin/8-16-stable:lib/support/nginx/gitlab-ssl
+
+# For HTTP configurations
+git diff origin/8-15-stable:lib/support/nginx/gitlab origin/8-16-stable:lib/support/nginx/gitlab
+```
+
+If you are using Apache instead of NGINX please see the updated [Apache templates].
+Also note that because Apache does not support upstreams behind Unix sockets you
+will need to let gitlab-workhorse listen on a TCP port. You can do this
+via [/etc/default/gitlab].
+
+[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
+[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/lib/support/init.d/gitlab.default.example#L38
+
+#### SMTP configuration
+
+If you're installing from source and use SMTP to deliver mail, you will need to add the following line
+to config/initializers/smtp_settings.rb:
+
+```ruby
+ActionMailer::Base.delivery_method = :smtp
+```
+
+See [smtp_settings.rb.sample] as an example.
+
+[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/config/initializers/smtp_settings.rb.sample#L13
+
+#### Init script
+
+Ensure you're still up-to-date with the latest init script changes:
+
+```bash
+cd /home/git/gitlab
+
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+For Ubuntu 16.04.1 LTS:
+
+```bash
+sudo systemctl daemon-reload
+```
+
+### 9. Start application
+
+```bash
+sudo service gitlab start
+sudo service nginx restart
+```
+
+### 10. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+```
+
+To make sure you didn't miss anything run a more thorough check:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```
+
+If all items are green, then congratulations, the upgrade is complete!
+
+## Things went south? Revert to previous version (8.15)
+
+### 1. Revert the code to the previous version
+
+Follow the [upgrade guide from 8.14 to 8.15](8.14-to-8.15.md), except for the
+database migration (the backup is already migrated to the previous version).
+
+### 2. Restore from the backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
+If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/config/gitlab.yml.example
diff --git a/doc/update/8.16-to-8.17.md b/doc/update/8.16-to-8.17.md
new file mode 100644
index 00000000000..74ffe0bc846
--- /dev/null
+++ b/doc/update/8.16-to-8.17.md
@@ -0,0 +1,268 @@
+# From 8.16 to 8.17
+
+Make sure you view this update guide from the tag (version) of GitLab you would
+like to install. In most cases this should be the highest numbered production
+tag (without rc in it). You can select the tag in the version dropdown at the
+top left corner of GitLab (below the menu bar).
+
+If the highest number stable branch is unclear please check the
+[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
+guide links by version.
+
+### 1. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
+### 2. Backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 3. Update Ruby
+
+We will continue supporting Ruby < 2.3 for the time being but we recommend you
+upgrade to Ruby 2.3 if you're running a source installation, as this is the same
+version that ships with our Omnibus package.
+
+You can check which version you are running with `ruby -v`.
+
+Download and compile Ruby:
+
+```bash
+mkdir /tmp/ruby && cd /tmp/ruby
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
+echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
+cd ruby-2.3.3
+./configure --disable-install-rdoc
+make
+sudo make install
+```
+
+Install Bundler:
+
+```bash
+sudo gem install bundler --no-ri --no-rdoc
+```
+
+### 4. Update Node
+
+GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
+it has a minimum requirement of node v4.3.0.
+
+You can check which version you are running with `node -v`. If you are running
+a version older than `v4.3.0` you will need to update to a newer version. You
+can find instructions to install from community maintained packages or compile
+from source at the nodejs.org website.
+
+<https://nodejs.org/en/download/>
+
+### 5. Get latest code
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 8-17-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 8-17-stable-ee
+```
+
+### 6. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without postgres')
+sudo -u git -H bundle install --without postgres development test --deployment
+
+# PostgreSQL installations (note: the line below states '--without mysql')
+sudo -u git -H bundle install --without mysql development test --deployment
+
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Install/update frontend asset dependencies
+sudo -u git -H npm install --production
+
+# Clean up assets and cache
+sudo -u git -H bundle exec rake gitlab:assets:clean gitlab:assets:compile cache:clear RAILS_ENV=production
+```
+
+**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
+
+### 7. Update gitlab-workhorse
+
+Install and compile gitlab-workhorse. This requires
+[Go 1.5](https://golang.org/dl) which should already be on your system from
+GitLab 8.1.
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production
+```
+
+### 8. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v4.1.1
+```
+
+### 9. Update configuration files
+
+#### New configuration options for `gitlab.yml`
+
+There might be new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/8-16-stable:config/gitlab.yml.example origin/8-17-stable:config/gitlab.yml.example
+```
+
+#### Git configuration
+
+Configure Git to generate packfile bitmaps (introduced in Git 2.0) on
+the GitLab server during `git gc`.
+
+```sh
+cd /home/git/gitlab
+
+sudo -u git -H git config --global repack.writeBitmaps true
+```
+
+#### Nginx configuration
+
+Ensure you're still up-to-date with the latest NGINX configuration changes:
+
+```sh
+cd /home/git/gitlab
+
+# For HTTPS configurations
+git diff origin/8-16-stable:lib/support/nginx/gitlab-ssl origin/8-17-stable:lib/support/nginx/gitlab-ssl
+
+# For HTTP configurations
+git diff origin/8-16-stable:lib/support/nginx/gitlab origin/8-17-stable:lib/support/nginx/gitlab
+```
+
+If you are using Apache instead of NGINX please see the updated [Apache templates].
+Also note that because Apache does not support upstreams behind Unix sockets you
+will need to let gitlab-workhorse listen on a TCP port. You can do this
+via [/etc/default/gitlab].
+
+[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
+[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-17-stable/lib/support/init.d/gitlab.default.example#L38
+
+#### SMTP configuration
+
+If you're installing from source and use SMTP to deliver mail, you will need to add the following line
+to config/initializers/smtp_settings.rb:
+
+```ruby
+ActionMailer::Base.delivery_method = :smtp
+```
+
+See [smtp_settings.rb.sample] as an example.
+
+[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-17-stable/config/initializers/smtp_settings.rb.sample#L13
+
+#### Init script
+
+There might be new configuration options available for [`gitlab.default.example`][gl-example].
+You need to update this file if you want to [enable GitLab Pages][pages-admin].
+View them with the command below and apply them manually to your current `/etc/default/gitlab`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/8-16-stable:lib/support/init.d/gitlab.default.example origin/8-17-stable:lib/support/init.d/gitlab.default.example
+```
+
+Ensure you're still up-to-date with the latest init script changes:
+
+```bash
+cd /home/git/gitlab
+
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+For Ubuntu 16.04.1 LTS:
+
+```bash
+sudo systemctl daemon-reload
+```
+
+### 10. Start application
+
+```bash
+sudo service gitlab start
+sudo service nginx restart
+```
+
+### 11. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+```
+
+To make sure you didn't miss anything run a more thorough check:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```
+
+If all items are green, then congratulations, the upgrade is complete!
+
+## Things went south? Revert to previous version (8.16)
+
+### 1. Revert the code to the previous version
+
+Follow the [upgrade guide from 8.15 to 8.16](8.15-to-8.16.md), except for the
+database migration (the backup is already migrated to the previous version).
+
+### 2. Restore from the backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
+If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-17-stable/config/gitlab.yml.example
+[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-17-stable/lib/support/init.d/gitlab.default.example
+[pages-admin]: ../administration/pages/source.md
diff --git a/doc/update/8.17-to-9.0.md b/doc/update/8.17-to-9.0.md
new file mode 100644
index 00000000000..6308317b1f2
--- /dev/null
+++ b/doc/update/8.17-to-9.0.md
@@ -0,0 +1,341 @@
+# From 8.17 to 9.0
+
+Make sure you view this update guide from the tag (version) of GitLab you would
+like to install. In most cases this should be the highest numbered production
+tag (without rc in it). You can select the tag in the version dropdown at the
+top left corner of GitLab (below the menu bar).
+
+If the highest number stable branch is unclear please check the
+[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
+guide links by version.
+
+### 1. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
+### 2. Backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 3. Update Ruby
+
+NOTE: GitLab 9.0 only supports Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
+sure to upgrade your interpreter if necessary.
+
+You can check which version you are running with `ruby -v`.
+
+Download and compile Ruby:
+
+```bash
+mkdir /tmp/ruby && cd /tmp/ruby
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
+echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
+cd ruby-2.3.3
+./configure --disable-install-rdoc
+make
+sudo make install
+```
+
+Install Bundler:
+
+```bash
+sudo gem install bundler --no-ri --no-rdoc
+```
+
+### 4. Update Node
+
+GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
+it has a minimum requirement of node v4.3.0.
+
+You can check which version you are running with `node -v`. If you are running
+a version older than `v4.3.0` you will need to update to a newer version. You
+can find instructions to install from community maintained packages or compile
+from source at the nodejs.org website.
+
+<https://nodejs.org/en/download/>
+
+
+Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
+JavaScript dependencies.
+
+```bash
+curl --location https://yarnpkg.com/install.sh | bash -
+```
+
+More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
+
+### 5. Get latest code
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 9-0-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 9-0-stable-ee
+```
+
+### 6. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
+```
+
+### 7. Update gitlab-workhorse
+
+Install and compile gitlab-workhorse. This requires
+[Go 1.5](https://golang.org/dl) which should already be on your system from
+GitLab 8.1. GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/).
+If you are not using Linux you may have to run `gmake` instead of
+`make` below.
+
+```bash
+cd /home/git/gitlab-workhorse
+
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
+sudo -u git -H make
+```
+
+### 8. Update configuration files
+
+#### New configuration options for `gitlab.yml`
+
+There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/8-17-stable:config/gitlab.yml.example origin/9-0-stable:config/gitlab.yml.example
+```
+
+#### Configuration changes for repository storages
+
+This version introduces a new configuration structure for repository storages.
+Update your current configuration as follows, replacing with your storages names and paths:
+
+**For installations from source**
+
+1. Update your `gitlab.yml`, from
+
+ ```yaml
+ repositories:
+ storages: # You must have at least a 'default' storage path.
+ default: /home/git/repositories
+ nfs: /mnt/nfs/repositories
+ cephfs: /mnt/cephfs/repositories
+ ```
+
+ to
+
+ ```yaml
+ repositories:
+ storages: # You must have at least a 'default' storage path.
+ default:
+ path: /home/git/repositories
+ nfs:
+ path: /mnt/nfs/repositories
+ cephfs:
+ path: /mnt/cephfs/repositories
+ ```
+
+**For Omnibus installations**
+
+1. Update your `/etc/gitlab/gitlab.rb`, from
+
+ ```ruby
+ git_data_dirs({
+ "default" => "/var/opt/gitlab/git-data",
+ "nfs" => "/mnt/nfs/git-data",
+ "cephfs" => "/mnt/cephfs/git-data"
+ })
+ ```
+
+ to
+
+ ```ruby
+ git_data_dirs({
+ "default" => { "path" => "/var/opt/gitlab/git-data" },
+ "nfs" => { "path" => "/mnt/nfs/git-data" },
+ "cephfs" => { "path" => "/mnt/cephfs/git-data" }
+ })
+ ```
+
+#### Git configuration
+
+Configure Git to generate packfile bitmaps (introduced in Git 2.0) on
+the GitLab server during `git gc`.
+
+```sh
+cd /home/git/gitlab
+
+sudo -u git -H git config --global repack.writeBitmaps true
+```
+
+#### Nginx configuration
+
+Ensure you're still up-to-date with the latest NGINX configuration changes:
+
+```sh
+cd /home/git/gitlab
+
+# For HTTPS configurations
+git diff origin/8-17-stable:lib/support/nginx/gitlab-ssl origin/9-0-stable:lib/support/nginx/gitlab-ssl
+
+# For HTTP configurations
+git diff origin/8-17-stable:lib/support/nginx/gitlab origin/9-0-stable:lib/support/nginx/gitlab
+```
+
+If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
+configuration as GitLab application no longer handles setting it.
+
+If you are using Apache instead of NGINX please see the updated [Apache templates].
+Also note that because Apache does not support upstreams behind Unix sockets you
+will need to let gitlab-workhorse listen on a TCP port. You can do this
+via [/etc/default/gitlab].
+
+[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
+[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-0-stable/lib/support/init.d/gitlab.default.example#L38
+
+#### SMTP configuration
+
+If you're installing from source and use SMTP to deliver mail, you will need to add the following line
+to config/initializers/smtp_settings.rb:
+
+```ruby
+ActionMailer::Base.delivery_method = :smtp
+```
+
+See [smtp_settings.rb.sample] as an example.
+
+[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-17-stable/config/initializers/smtp_settings.rb.sample#L13
+
+#### Init script
+
+There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/8-17-stable:lib/support/init.d/gitlab.default.example origin/9-0-stable:lib/support/init.d/gitlab.default.example
+```
+
+Ensure you're still up-to-date with the latest init script changes:
+
+```bash
+cd /home/git/gitlab
+
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+For Ubuntu 16.04.1 LTS:
+
+```bash
+sudo systemctl daemon-reload
+```
+
+### 9. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without postgres')
+sudo -u git -H bundle install --without postgres development test --deployment
+
+# PostgreSQL installations (note: the line below states '--without mysql')
+sudo -u git -H bundle install --without mysql development test --deployment
+
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Update node dependencies and recompile assets
+sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
+
+# Clean up cache
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
+```
+
+**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
+
+### 10. Optional: install Gitaly
+
+Gitaly is still an optional component of GitLab. If you want to save time
+during your 9.0 upgrade **you can skip this step**.
+
+If you do want to set up Gitaly in GitLab 9.0 then follow [Gitaly section of the installation
+guide](../install/installation.md#install-gitaly).
+
+### 11. Start application
+
+```bash
+sudo service gitlab start
+sudo service nginx restart
+```
+
+### 12. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+```
+
+To make sure you didn't miss anything run a more thorough check:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```
+
+If all items are green, then congratulations, the upgrade is complete!
+
+## Things went south? Revert to previous version (8.17)
+
+### 1. Revert the code to the previous version
+
+Follow the [upgrade guide from 8.16 to 8.17](8.16-to-8.17.md), except for the
+database migration (the backup is already migrated to the previous version).
+
+### 2. Restore from the backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
+If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-0-stable/config/gitlab.yml.example
+[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-0-stable/lib/support/init.d/gitlab.default.example
diff --git a/doc/update/8.2-to-8.3.md b/doc/update/8.2-to-8.3.md
index dd3fdafd8d1..4b3c5bf6d64 100644
--- a/doc/update/8.2-to-8.3.md
+++ b/doc/update/8.2-to-8.3.md
@@ -114,12 +114,20 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/8-2-stable:config/gitlab.yml.example origin/8-3-stable:config/gitlab.yml.example
```
+#### GitLab default file
+
+The value of the `gitlab_workhorse_options` variable should be updated within the default gitlab file (`/etc/default/gitlab`) according to the following diff:
+
+```sh
+git diff origin/8-2-stable:lib/support/init.d/gitlab.default.example origin/8-3-stable:lib/support/init.d/gitlab.default.example
+```
+
#### Nginx configuration
GitLab 8.3 introduces major changes in the NGINX configuration.
@@ -211,3 +219,5 @@ If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of
### "You appear to have cloned an empty repository."
See the [7.14 to 8.0 update guide](7.14-to-8.0.md#troubleshooting).
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-3-stable/config/gitlab.yml.example
diff --git a/doc/update/8.3-to-8.4.md b/doc/update/8.3-to-8.4.md
index e62d894609a..8b89455ca87 100644
--- a/doc/update/8.3-to-8.4.md
+++ b/doc/update/8.3-to-8.4.md
@@ -84,7 +84,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/8-3-stable:config/gitlab.yml.example origin/8-4-stable:config/gitlab.yml.example
@@ -98,7 +98,7 @@ We updated the init script for GitLab in order to set a specific PATH for gitlab
cd /home/git/gitlab
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
```
-
+
For Ubuntu 16.04.1 LTS:
sudo systemctl daemon-reload
@@ -135,3 +135,5 @@ sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-4-stable/config/gitlab.yml.example
diff --git a/doc/update/8.4-to-8.5.md b/doc/update/8.4-to-8.5.md
index 678cc69d773..0eedfaee2db 100644
--- a/doc/update/8.4-to-8.5.md
+++ b/doc/update/8.4-to-8.5.md
@@ -88,7 +88,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/8-4-stable:config/gitlab.yml.example origin/8-5-stable:config/gitlab.yml.example
@@ -119,7 +119,7 @@ via [/etc/default/gitlab].
Ensure you're still up-to-date with the latest init script changes:
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-
+
For Ubuntu 16.04.1 LTS:
sudo systemctl daemon-reload
@@ -156,3 +156,5 @@ sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-5-stable/config/gitlab.yml.example
diff --git a/doc/update/8.5-to-8.6.md b/doc/update/8.5-to-8.6.md
index a76346516b9..851056161bb 100644
--- a/doc/update/8.5-to-8.6.md
+++ b/doc/update/8.5-to-8.6.md
@@ -107,7 +107,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/8-5-stable:config/gitlab.yml.example origin/8-6-stable:config/gitlab.yml.example
@@ -175,3 +175,5 @@ sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-6-stable/config/gitlab.yml.example
diff --git a/doc/update/8.6-to-8.7.md b/doc/update/8.6-to-8.7.md
index 05ef4e61759..34c727260aa 100644
--- a/doc/update/8.6-to-8.7.md
+++ b/doc/update/8.6-to-8.7.md
@@ -88,7 +88,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/8-6-stable:config/gitlab.yml.example origin/8-7-stable:config/gitlab.yml.example
@@ -164,3 +164,5 @@ sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-7-stable/config/gitlab.yml.example
diff --git a/doc/update/8.7-to-8.8.md b/doc/update/8.7-to-8.8.md
index 8ce434e5f78..6feeb1919de 100644
--- a/doc/update/8.7-to-8.8.md
+++ b/doc/update/8.7-to-8.8.md
@@ -88,7 +88,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/8-7-stable:config/gitlab.yml.example origin/8-8-stable:config/gitlab.yml.example
@@ -164,3 +164,5 @@ sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-8-stable/config/gitlab.yml.example
diff --git a/doc/update/8.8-to-8.9.md b/doc/update/8.8-to-8.9.md
index aa077316bbe..61cdf8854d4 100644
--- a/doc/update/8.8-to-8.9.md
+++ b/doc/update/8.8-to-8.9.md
@@ -104,7 +104,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/8-8-stable:config/gitlab.yml.example origin/8-9-stable:config/gitlab.yml.example
@@ -193,3 +193,5 @@ sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-9-stable/config/gitlab.yml.example
diff --git a/doc/update/8.9-to-8.10.md b/doc/update/8.9-to-8.10.md
index bb2c79fbb84..d6b2f11d49a 100644
--- a/doc/update/8.9-to-8.10.md
+++ b/doc/update/8.9-to-8.10.md
@@ -104,7 +104,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
#### New configuration options for `gitlab.yml`
-There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+There are new configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
```sh
git diff origin/8-9-stable:config/gitlab.yml.example origin/8-10-stable:config/gitlab.yml.example
@@ -193,3 +193,5 @@ sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-10-stable/config/gitlab.yml.example
diff --git a/doc/update/9.0-to-9.1.md b/doc/update/9.0-to-9.1.md
new file mode 100644
index 00000000000..2d597894517
--- /dev/null
+++ b/doc/update/9.0-to-9.1.md
@@ -0,0 +1,390 @@
+# From 9.0 to 9.1
+
+Make sure you view this update guide from the tag (version) of GitLab you would
+like to install. In most cases this should be the highest numbered production
+tag (without rc in it). You can select the tag in the version dropdown at the
+top left corner of GitLab (below the menu bar).
+
+If the highest number stable branch is unclear please check the
+[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
+guide links by version.
+
+### 1. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
+### 2. Backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 3. Update Ruby
+
+NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
+sure to upgrade your interpreter if necessary.
+
+You can check which version you are running with `ruby -v`.
+
+Download and compile Ruby:
+
+```bash
+mkdir /tmp/ruby && cd /tmp/ruby
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
+echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
+cd ruby-2.3.3
+./configure --disable-install-rdoc
+make
+sudo make install
+```
+
+Install Bundler:
+
+```bash
+sudo gem install bundler --no-ri --no-rdoc
+```
+
+### 4. Update Node
+
+GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
+it has a minimum requirement of node v4.3.0.
+
+You can check which version you are running with `node -v`. If you are running
+a version older than `v4.3.0` you will need to update to a newer version. You
+can find instructions to install from community maintained packages or compile
+from source at the nodejs.org website.
+
+<https://nodejs.org/en/download/>
+
+
+Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
+JavaScript dependencies.
+
+```bash
+curl --location https://yarnpkg.com/install.sh | bash -
+```
+
+More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
+
+### 5. Get latest code
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 9-1-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 9-1-stable-ee
+```
+
+### 6. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
+```
+
+### 7. Update gitlab-workhorse
+
+Install and compile gitlab-workhorse. This requires
+[Go 1.5](https://golang.org/dl) which should already be on your system from
+GitLab 8.1. GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/).
+If you are not using Linux you may have to run `gmake` instead of
+`make` below.
+
+```bash
+cd /home/git/gitlab-workhorse
+
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
+sudo -u git -H make
+```
+
+### 8. Update configuration files
+
+#### New configuration options for `gitlab.yml`
+
+There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/9-0-stable:config/gitlab.yml.example origin/9-1-stable:config/gitlab.yml.example
+```
+
+#### Configuration changes for repository storages
+
+This version introduces a new configuration structure for repository storages.
+Update your current configuration as follows, replacing with your storages names and paths:
+
+**For installations from source**
+
+1. Update your `gitlab.yml`, from
+
+ ```yaml
+ repositories:
+ storages: # You must have at least a 'default' storage path.
+ default: /home/git/repositories
+ nfs: /mnt/nfs/repositories
+ cephfs: /mnt/cephfs/repositories
+ ```
+
+ to
+
+ ```yaml
+ repositories:
+ storages: # You must have at least a 'default' storage path.
+ default:
+ path: /home/git/repositories
+ nfs:
+ path: /mnt/nfs/repositories
+ cephfs:
+ path: /mnt/cephfs/repositories
+ ```
+
+**For Omnibus installations**
+
+1. Update your `/etc/gitlab/gitlab.rb`, from
+
+ ```ruby
+ git_data_dirs({
+ "default" => "/var/opt/gitlab/git-data",
+ "nfs" => "/mnt/nfs/git-data",
+ "cephfs" => "/mnt/cephfs/git-data"
+ })
+ ```
+
+ to
+
+ ```ruby
+ git_data_dirs({
+ "default" => { "path" => "/var/opt/gitlab/git-data" },
+ "nfs" => { "path" => "/mnt/nfs/git-data" },
+ "cephfs" => { "path" => "/mnt/cephfs/git-data" }
+ })
+ ```
+
+#### Git configuration
+
+Configure Git to generate packfile bitmaps (introduced in Git 2.0) on
+the GitLab server during `git gc`.
+
+```sh
+cd /home/git/gitlab
+
+sudo -u git -H git config --global repack.writeBitmaps true
+```
+
+#### Nginx configuration
+
+Ensure you're still up-to-date with the latest NGINX configuration changes:
+
+```sh
+cd /home/git/gitlab
+
+# For HTTPS configurations
+git diff origin/9-0-stable:lib/support/nginx/gitlab-ssl origin/9-1-stable:lib/support/nginx/gitlab-ssl
+
+# For HTTP configurations
+git diff origin/9-0-stable:lib/support/nginx/gitlab origin/9-1-stable:lib/support/nginx/gitlab
+```
+
+If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
+configuration as GitLab application no longer handles setting it.
+
+If you are using Apache instead of NGINX please see the updated [Apache templates].
+Also note that because Apache does not support upstreams behind Unix sockets you
+will need to let gitlab-workhorse listen on a TCP port. You can do this
+via [/etc/default/gitlab].
+
+[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
+[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-1-stable/lib/support/init.d/gitlab.default.example#L38
+
+#### SMTP configuration
+
+If you're installing from source and use SMTP to deliver mail, you will need to add the following line
+to config/initializers/smtp_settings.rb:
+
+```ruby
+ActionMailer::Base.delivery_method = :smtp
+```
+
+See [smtp_settings.rb.sample] as an example.
+
+[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-0-stable/config/initializers/smtp_settings.rb.sample#L13
+
+#### Init script
+
+There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/9-0-stable:lib/support/init.d/gitlab.default.example origin/9-1-stable:lib/support/init.d/gitlab.default.example
+```
+
+Ensure you're still up-to-date with the latest init script changes:
+
+```bash
+cd /home/git/gitlab
+
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+For Ubuntu 16.04.1 LTS:
+
+```bash
+sudo systemctl daemon-reload
+```
+
+### 9. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without postgres')
+sudo -u git -H bundle install --without postgres development test --deployment
+
+# PostgreSQL installations (note: the line below states '--without mysql')
+sudo -u git -H bundle install --without mysql development test --deployment
+
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Update node dependencies and recompile assets
+sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
+
+# Clean up cache
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
+```
+
+**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
+
+### 10. Optional: install Gitaly
+
+Gitaly is still an optional component of GitLab. If you want to save time
+during your 9.1 upgrade **you can skip this step**.
+
+If you have not yet set up Gitaly then follow [Gitaly section of the installation
+guide](../install/installation.md#install-gitaly).
+
+If you installed Gitaly in GitLab 9.0 you need to make some changes in
+gitlab.yml, and create a new config.toml file.
+
+#### Gitaly gitlab.yml changes
+
+Look for `socket_path:` the `gitaly:` section. Its value is usually
+`/home/git/gitlab/tmp/sockets/private/gitaly.socket`. Note what socket
+path your gitlab.yml is using. Now go to the `repositories:` section,
+and for each entry under `storages:`, add a `gitaly_address:` based on
+the socket path, but with `unix:` in front.
+
+```yaml
+ repositories:
+ storages:
+ default:
+ path: /home/git/repositories
+ gitaly_address: unix:/home/git/gitlab/tmp/sockets/private/gitaly.socket
+ other_storage:
+ path: /home/git/other-repositories
+ gitaly_address: unix:/home/git/gitlab/tmp/sockets/private/gitaly.socket
+```
+
+Each entry under `storages:` should use the same `gitaly_address`.
+
+#### Compile Gitaly
+
+This step will also create `config.toml.example` which you need below.
+
+```shell
+cd /home/git/gitaly
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
+sudo -u git -H make
+```
+
+#### Gitaly config.toml
+
+In GitLab 9.1 we are replacing environment variables in Gitaly with a
+TOML configuration file.
+
+```shell
+cd /home/git/gitaly
+
+sudo mv env env.old
+sudo -u git cp config.toml.example config.toml
+# If you are using custom repository storage paths they need to be in config.toml
+sudo -u git -H editor config.toml
+```
+
+### 11. Start application
+
+```bash
+sudo service gitlab start
+sudo service nginx restart
+```
+
+### 12. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+```
+
+To make sure you didn't miss anything run a more thorough check:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```
+
+If all items are green, then congratulations, the upgrade is complete!
+
+## Things went south? Revert to previous version (9.0)
+
+### 1. Revert the code to the previous version
+
+Follow the [upgrade guide from 8.17 to 9.0](8.17-to-9.0.md), except for the
+database migration (the backup is already migrated to the previous version).
+
+### 2. Restore from the backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
+If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-1-stable/config/gitlab.yml.example
+[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-1-stable/lib/support/init.d/gitlab.default.example
diff --git a/doc/update/9.1-to-9.2.md b/doc/update/9.1-to-9.2.md
new file mode 100644
index 00000000000..e7d97fde14e
--- /dev/null
+++ b/doc/update/9.1-to-9.2.md
@@ -0,0 +1,288 @@
+# From 9.1 to 9.2
+
+Make sure you view this update guide from the tag (version) of GitLab you would
+like to install. In most cases this should be the highest numbered production
+tag (without rc in it). You can select the tag in the version dropdown at the
+top left corner of GitLab (below the menu bar).
+
+If the highest number stable branch is unclear please check the
+[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
+guide links by version.
+
+### 1. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
+### 2. Backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 3. Update Ruby
+
+NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
+sure to upgrade your interpreter if necessary.
+
+You can check which version you are running with `ruby -v`.
+
+Download and compile Ruby:
+
+```bash
+mkdir /tmp/ruby && cd /tmp/ruby
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
+echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
+cd ruby-2.3.3
+./configure --disable-install-rdoc
+make
+sudo make install
+```
+
+Install Bundler:
+
+```bash
+sudo gem install bundler --no-ri --no-rdoc
+```
+
+### 4. Update Node
+
+GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
+it has a minimum requirement of node v4.3.0.
+
+You can check which version you are running with `node -v`. If you are running
+a version older than `v4.3.0` you will need to update to a newer version. You
+can find instructions to install from community maintained packages or compile
+from source at the nodejs.org website.
+
+<https://nodejs.org/en/download/>
+
+
+Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
+JavaScript dependencies.
+
+```bash
+curl --location https://yarnpkg.com/install.sh | bash -
+```
+
+More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
+
+### 5. Get latest code
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 9-2-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 9-2-stable-ee
+```
+
+### 6. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
+sudo -u git -H bin/compile
+```
+
+### 7. Update gitlab-workhorse
+
+Install and compile gitlab-workhorse. This requires
+[Go 1.8](https://golang.org/dl). Go (at least 1.5) should already be on your system from
+GitLab 8.1 and shall be upgraded if necessary. Please note that starting in Gitlab 9.3, only Go 1.8.3 and above will be supported. GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/).
+If you are not using Linux you may have to run `gmake` instead of
+`make` below.
+
+```bash
+cd /home/git/gitlab-workhorse
+
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
+sudo -u git -H make
+```
+
+### 8. Update configuration files
+
+#### New configuration options for `gitlab.yml`
+
+There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/9-1-stable:config/gitlab.yml.example origin/9-2-stable:config/gitlab.yml.example
+```
+
+#### Nginx configuration
+
+Ensure you're still up-to-date with the latest NGINX configuration changes:
+
+```sh
+cd /home/git/gitlab
+
+# For HTTPS configurations
+git diff origin/9-1-stable:lib/support/nginx/gitlab-ssl origin/9-2-stable:lib/support/nginx/gitlab-ssl
+
+# For HTTP configurations
+git diff origin/9-1-stable:lib/support/nginx/gitlab origin/9-2-stable:lib/support/nginx/gitlab
+```
+
+If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
+configuration as GitLab application no longer handles setting it.
+
+If you are using Apache instead of NGINX please see the updated [Apache templates].
+Also note that because Apache does not support upstreams behind Unix sockets you
+will need to let gitlab-workhorse listen on a TCP port. You can do this
+via [/etc/default/gitlab].
+
+[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
+[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-2-stable/lib/support/init.d/gitlab.default.example#L38
+
+#### SMTP configuration
+
+If you're installing from source and use SMTP to deliver mail, you will need to add the following line
+to config/initializers/smtp_settings.rb:
+
+```ruby
+ActionMailer::Base.delivery_method = :smtp
+```
+
+See [smtp_settings.rb.sample] as an example.
+
+[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-1-stable/config/initializers/smtp_settings.rb.sample#L13
+
+#### Init script
+
+There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/9-1-stable:lib/support/init.d/gitlab.default.example origin/9-2-stable:lib/support/init.d/gitlab.default.example
+```
+
+Ensure you're still up-to-date with the latest init script changes:
+
+```bash
+cd /home/git/gitlab
+
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+For Ubuntu 16.04.1 LTS:
+
+```bash
+sudo systemctl daemon-reload
+```
+
+### 9. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without postgres')
+sudo -u git -H bundle install --without postgres development test --deployment
+
+# PostgreSQL installations (note: the line below states '--without mysql')
+sudo -u git -H bundle install --without mysql development test --deployment
+
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Update node dependencies and recompile assets
+sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
+
+# Clean up cache
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
+```
+
+**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
+
+### 10. Optional: install Gitaly
+
+Gitaly is still an optional component of GitLab. If you want to save time
+during your 9.2 upgrade **you can skip this step**.
+
+If you have not yet set up Gitaly then follow [Gitaly section of the installation
+guide](../install/installation.md#install-gitaly).
+
+#### Compile Gitaly
+
+```shell
+cd /home/git/gitaly
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
+sudo -u git -H make
+```
+
+### 11. Start application
+
+```bash
+sudo service gitlab start
+sudo service nginx restart
+```
+
+### 12. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+```
+
+To make sure you didn't miss anything run a more thorough check:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```
+
+If all items are green, then congratulations, the upgrade is complete!
+
+## Things went south? Revert to previous version (9.1)
+
+### 1. Revert the code to the previous version
+
+Follow the [upgrade guide from 9.0 to 9.1](9.0-to-9.1.md), except for the
+database migration (the backup is already migrated to the previous version).
+
+### 2. Restore from the backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
+If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-2-stable/config/gitlab.yml.example
+[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-2-stable/lib/support/init.d/gitlab.default.example
diff --git a/doc/update/9.2-to-9.3.md b/doc/update/9.2-to-9.3.md
new file mode 100644
index 00000000000..0c32e4db53f
--- /dev/null
+++ b/doc/update/9.2-to-9.3.md
@@ -0,0 +1,305 @@
+# From 9.2 to 9.3
+
+Make sure you view this update guide from the tag (version) of GitLab you would
+like to install. In most cases this should be the highest numbered production
+tag (without rc in it). You can select the tag in the version dropdown at the
+top left corner of GitLab (below the menu bar).
+
+If the highest number stable branch is unclear please check the
+[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
+guide links by version.
+
+### 1. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
+### 2. Backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 3. Update Ruby
+
+NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
+sure to upgrade your interpreter if necessary.
+
+You can check which version you are running with `ruby -v`.
+
+Download and compile Ruby:
+
+```bash
+mkdir /tmp/ruby && cd /tmp/ruby
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
+echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
+cd ruby-2.3.3
+./configure --disable-install-rdoc
+make
+sudo make install
+```
+
+Install Bundler:
+
+```bash
+sudo gem install bundler --no-ri --no-rdoc
+```
+
+### 4. Update Node
+
+GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
+it has a minimum requirement of node v4.3.0.
+
+You can check which version you are running with `node -v`. If you are running
+a version older than `v4.3.0` you will need to update to a newer version. You
+can find instructions to install from community maintained packages or compile
+from source at the nodejs.org website.
+
+<https://nodejs.org/en/download/>
+
+
+Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
+JavaScript dependencies.
+
+```bash
+curl --location https://yarnpkg.com/install.sh | bash -
+```
+
+More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
+
+### 5. Update Go
+
+NOTE: GitLab 9.3 and higher only supports Go 1.8.3 and dropped support for Go 1.5.x through 1.7.x. Be
+sure to upgrade your installation if necessary
+
+You can check which version you are running with `go version`.
+
+Download and install Go:
+
+```bash
+# Remove former Go installation folder
+sudo rm -rf /usr/local/go
+
+curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
+echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
+ sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
+sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
+rm go1.8.3.linux-amd64.tar.gz
+```
+
+### 6. Get latest code
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 9-3-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 9-3-stable-ee
+```
+
+### 5. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
+sudo -u git -H bin/compile
+```
+
+### 6. Update gitlab-workhorse
+
+Install and compile gitlab-workhorse. This requires
+[Go 1.5](https://golang.org/dl) which should already be on your system from
+GitLab 8.1. GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/).
+If you are not using Linux you may have to run `gmake` instead of
+`make` below.
+
+```bash
+cd /home/git/gitlab-workhorse
+
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
+sudo -u git -H make
+```
+
+### 7. Update Gitaly
+
+If you have not yet set up Gitaly then follow [Gitaly section of the installation
+guide](../install/installation.md#install-gitaly).
+
+#### Compile Gitaly
+
+```shell
+cd /home/git/gitaly
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
+sudo -u git -H make
+```
+
+### 10. Update configuration files
+
+#### New configuration options for `gitlab.yml`
+
+There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/9-2-stable:config/gitlab.yml.example origin/9-3-stable:config/gitlab.yml.example
+```
+
+#### Nginx configuration
+
+Ensure you're still up-to-date with the latest NGINX configuration changes:
+
+```sh
+cd /home/git/gitlab
+
+# For HTTPS configurations
+git diff origin/9-2-stable:lib/support/nginx/gitlab-ssl origin/9-3-stable:lib/support/nginx/gitlab-ssl
+
+# For HTTP configurations
+git diff origin/9-2-stable:lib/support/nginx/gitlab origin/9-3-stable:lib/support/nginx/gitlab
+```
+
+If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
+configuration as GitLab application no longer handles setting it.
+
+If you are using Apache instead of NGINX please see the updated [Apache templates].
+Also note that because Apache does not support upstreams behind Unix sockets you
+will need to let gitlab-workhorse listen on a TCP port. You can do this
+via [/etc/default/gitlab].
+
+[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
+[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-3-stable/lib/support/init.d/gitlab.default.example#L38
+
+#### SMTP configuration
+
+If you're installing from source and use SMTP to deliver mail, you will need to add the following line
+to config/initializers/smtp_settings.rb:
+
+```ruby
+ActionMailer::Base.delivery_method = :smtp
+```
+
+See [smtp_settings.rb.sample] as an example.
+
+[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-2-stable/config/initializers/smtp_settings.rb.sample#L13
+
+#### Init script
+
+There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/9-2-stable:lib/support/init.d/gitlab.default.example origin/9-3-stable:lib/support/init.d/gitlab.default.example
+```
+
+Ensure you're still up-to-date with the latest init script changes:
+
+```bash
+cd /home/git/gitlab
+
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+For Ubuntu 16.04.1 LTS:
+
+```bash
+sudo systemctl daemon-reload
+```
+
+### 11. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without postgres')
+sudo -u git -H bundle install --without postgres development test --deployment
+
+# PostgreSQL installations (note: the line below states '--without mysql')
+sudo -u git -H bundle install --without mysql development test --deployment
+
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Update node dependencies and recompile assets
+sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
+
+# Clean up cache
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
+```
+
+**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
+
+### 12. Start application
+
+```bash
+sudo service gitlab start
+sudo service nginx restart
+```
+
+### 13. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+```
+
+To make sure you didn't miss anything run a more thorough check:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```
+
+If all items are green, then congratulations, the upgrade is complete!
+
+## Things went south? Revert to previous version (9.2)
+
+### 1. Revert the code to the previous version
+
+Follow the [upgrade guide from 9.1 to 9.2](9.1-to-9.2.md), except for the
+database migration (the backup is already migrated to the previous version).
+
+### 2. Restore from the backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
+If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-3-stable/config/gitlab.yml.example
+[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-3-stable/lib/support/init.d/gitlab.default.example
diff --git a/doc/update/9.3-to-9.4.md b/doc/update/9.3-to-9.4.md
new file mode 100644
index 00000000000..a712ce5a8b1
--- /dev/null
+++ b/doc/update/9.3-to-9.4.md
@@ -0,0 +1,317 @@
+# From 9.3 to 9.4
+
+Make sure you view this update guide from the tag (version) of GitLab you would
+like to install. In most cases this should be the highest numbered production
+tag (without rc in it). You can select the tag in the version dropdown at the
+top left corner of GitLab (below the menu bar).
+
+If the highest number stable branch is unclear please check the
+[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
+guide links by version.
+
+### 1. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
+### 2. Backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 3. Update Ruby
+
+NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be
+sure to upgrade your interpreter if necessary.
+
+You can check which version you are running with `ruby -v`.
+
+Download and compile Ruby:
+
+```bash
+mkdir /tmp/ruby && cd /tmp/ruby
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz
+echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz
+cd ruby-2.3.3
+./configure --disable-install-rdoc
+make
+sudo make install
+```
+
+Install Bundler:
+
+```bash
+sudo gem install bundler --no-ri --no-rdoc
+```
+
+### 4. Update Node
+
+GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and
+it has a minimum requirement of node v4.3.0.
+
+You can check which version you are running with `node -v`. If you are running
+a version older than `v4.3.0` you will need to update to a newer version. You
+can find instructions to install from community maintained packages or compile
+from source at the nodejs.org website.
+
+<https://nodejs.org/en/download/>
+
+
+Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage
+JavaScript dependencies.
+
+```bash
+curl --location https://yarnpkg.com/install.sh | bash -
+```
+
+More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
+
+### 5. Update Go
+
+NOTE: GitLab 9.4 and higher only supports Go 1.8.3 and dropped support for Go 1.5.x through 1.7.x. Be
+sure to upgrade your installation if necessary
+
+You can check which version you are running with `go version`.
+
+Download and install Go:
+
+```bash
+# Remove former Go installation folder
+sudo rm -rf /usr/local/go
+
+curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
+echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
+ sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
+sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
+rm go1.8.3.linux-amd64.tar.gz
+```
+
+### 6. Get latest code
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git fetch --all
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+```
+
+For GitLab Community Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 9-4-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 9-4-stable-ee
+```
+
+### 5. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
+sudo -u git -H bin/compile
+```
+
+### 6. Update gitlab-workhorse
+
+Install and compile gitlab-workhorse. This requires
+[Go 1.8](https://golang.org/dl) which should already be on your system from
+GitLab 8.1. GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/).
+If you are not using Linux you may have to run `gmake` instead of
+`make` below.
+
+```bash
+cd /home/git/gitlab-workhorse
+
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
+sudo -u git -H make
+```
+
+### 7. Update Gitaly
+
+If you have not yet set up Gitaly then follow [Gitaly section of the installation
+guide](../install/installation.md#install-gitaly).
+
+#### Check Gitaly configuration
+
+Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
+configuration file may contain syntax errors. The block name
+`[[storages]]`, which may occur more than once in your `config.toml`
+file, should be `[[storage]]` instead.
+
+```shell
+cd /home/git/gitaly
+sudo -u git -H editor config.toml
+```
+
+#### Compile Gitaly
+
+```shell
+cd /home/git/gitaly
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
+sudo -u git -H make
+```
+
+### 10. Update configuration files
+
+#### New configuration options for `gitlab.yml`
+
+There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/9-3-stable:config/gitlab.yml.example origin/9-4-stable:config/gitlab.yml.example
+```
+
+#### Nginx configuration
+
+Ensure you're still up-to-date with the latest NGINX configuration changes:
+
+```sh
+cd /home/git/gitlab
+
+# For HTTPS configurations
+git diff origin/9-3-stable:lib/support/nginx/gitlab-ssl origin/9-4-stable:lib/support/nginx/gitlab-ssl
+
+# For HTTP configurations
+git diff origin/9-3-stable:lib/support/nginx/gitlab origin/9-4-stable:lib/support/nginx/gitlab
+```
+
+If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
+configuration as GitLab application no longer handles setting it.
+
+If you are using Apache instead of NGINX please see the updated [Apache templates].
+Also note that because Apache does not support upstreams behind Unix sockets you
+will need to let gitlab-workhorse listen on a TCP port. You can do this
+via [/etc/default/gitlab].
+
+[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
+[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-4-stable/lib/support/init.d/gitlab.default.example#L38
+
+#### SMTP configuration
+
+If you're installing from source and use SMTP to deliver mail, you will need to add the following line
+to config/initializers/smtp_settings.rb:
+
+```ruby
+ActionMailer::Base.delivery_method = :smtp
+```
+
+See [smtp_settings.rb.sample] as an example.
+
+[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-3-stable/config/initializers/smtp_settings.rb.sample#L13
+
+#### Init script
+
+There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/9-3-stable:lib/support/init.d/gitlab.default.example origin/9-4-stable:lib/support/init.d/gitlab.default.example
+```
+
+Ensure you're still up-to-date with the latest init script changes:
+
+```bash
+cd /home/git/gitlab
+
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+For Ubuntu 16.04.1 LTS:
+
+```bash
+sudo systemctl daemon-reload
+```
+
+### 11. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without postgres')
+sudo -u git -H bundle install --without postgres development test --deployment
+
+# PostgreSQL installations (note: the line below states '--without mysql')
+sudo -u git -H bundle install --without mysql development test --deployment
+
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Update node dependencies and recompile assets
+sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
+
+# Clean up cache
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
+```
+
+**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
+
+### 12. Start application
+
+```bash
+sudo service gitlab start
+sudo service nginx restart
+```
+
+### 13. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+```
+
+To make sure you didn't miss anything run a more thorough check:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```
+
+If all items are green, then congratulations, the upgrade is complete!
+
+## Things went south? Revert to previous version (9.3)
+
+### 1. Revert the code to the previous version
+
+Follow the [upgrade guide from 9.2 to 9.3](9.2-to-9.3.md), except for the
+database migration (the backup is already migrated to the previous version).
+
+### 2. Restore from the backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
+If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-4-stable/config/gitlab.yml.example
+[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-4-stable/lib/support/init.d/gitlab.default.example
diff --git a/doc/update/README.md b/doc/update/README.md
index 975d72164b4..22dbc7c750f 100644
--- a/doc/update/README.md
+++ b/doc/update/README.md
@@ -11,22 +11,6 @@ There are currently 3 official ways to install GitLab:
Based on your installation, choose a section below that fits your needs.
----
-
-<!-- START doctoc generated TOC please keep comment here to allow auto update -->
-<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
-**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
-
-- [Omnibus Packages](#omnibus-packages)
-- [Installation from source](#installation-from-source)
-- [Installation using Docker](#installation-using-docker)
-- [Upgrading between editions](#upgrading-between-editions)
- - [Community to Enterprise Edition](#community-to-enterprise-edition)
- - [Enterprise to Community Edition](#enterprise-to-community-edition)
-- [Miscellaneous](#miscellaneous)
-
-<!-- END doctoc generated TOC please keep comment here to allow auto update -->
-
## Omnibus Packages
- The [Omnibus update guide](http://docs.gitlab.com/omnibus/update/README.html)
@@ -48,6 +32,20 @@ GitLab provides official Docker images for both Community and Enterprise
editions. They are based on the Omnibus package and instructions on how to
update them are in [a separate document][omnidocker].
+## Upgrading without downtime
+
+Starting with GitLab 9.1.0 it's possible to upgrade to a newer major, minor, or patch version of GitLab
+without having to take your GitLab instance offline. However, for this to work
+there are the following requirements:
+
+1. You can only upgrade 1 minor release at a time. So from 9.1 to 9.2, not to 9.3.
+2. You have to be on the most recent patch release. For example, if 9.1.15 is the last
+ release of 9.1 then you can safely upgrade from that version to any 9.2.x version.
+ However, if you are running 9.1.14 you first need to upgrade to 9.1.15.
+2. You have to use [post-deployment
+ migrations](../development/post_deployment_migrations.md).
+3. You are using PostgreSQL. If you are using MySQL please look at the release post to see if downtime is required.
+
## Upgrading between editions
GitLab comes in two flavors: [Community Edition][ce] which is MIT licensed,
@@ -85,6 +83,8 @@ possible.
- [MySQL installation guide](../install/database_mysql.md) contains additional
information about configuring GitLab to work with a MySQL database.
- [Restoring from backup after a failed upgrade](restore_after_failure.md)
+- [Upgrading PostgreSQL Using Slony](upgrading_postgresql_using_slony.md), for
+ upgrading a PostgreSQL database with minimal downtime.
[omnidocker]: http://docs.gitlab.com/omnibus/docker/README.html
[source-ee]: https://gitlab.com/gitlab-org/gitlab-ee/tree/master/doc/update
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index 60729316cde..ac1bcb8f241 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -1,7 +1,10 @@
# Universal update guide for patch versions
-*Make sure you view this [upgrade guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/patch_versions.md) from the `master` branch for the most up to date instructions.*
-For example from 7.14.0 to 7.14.3, also see the [semantic versioning specification](http://semver.org/).
+## Select Version to Install
+
+Make sure you view [this update guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/patch_versions.md) from the tag (version) of GitLab you would like to install.
+In most cases this should be the highest numbered production tag (without rc in it).
+You can select the tag in the version dropdown in the top left corner of GitLab (below the menu bar).
### 0. Backup
@@ -11,6 +14,7 @@ user on the database version)
```bash
cd /home/git/gitlab
+
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
@@ -29,29 +33,13 @@ current version with `cat VERSION`).
```bash
cd /home/git/gitlab
+
sudo -u git -H git fetch --all
sudo -u git -H git checkout -- Gemfile.lock db/schema.rb
sudo -u git -H git checkout LATEST_TAG -b LATEST_TAG
```
-### 3. Update gitlab-shell to the corresponding version
-
-```bash
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION` -b v`cat /home/git/gitlab/GITLAB_SHELL_VERSION`
-```
-
-### 4. Update gitlab-workhorse to the corresponding version
-
-```bash
-cd /home/git/gitlab-workhorse
-sudo -u git -H git fetch
-sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_WORKHORSE_VERSION` -b v`cat /home/git/gitlab/GITLAB_WORKHORSE_VERSION`
-sudo -u git -H make
-```
-
-### 5. Install libs, migrations, etc.
+### 3. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
@@ -69,7 +57,25 @@ sudo -u git -H bundle clean
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
+sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile cache:clear RAILS_ENV=production NODE_ENV=production
+```
+
+### 4. Update gitlab-workhorse to the corresponding version
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production
+```
+
+### 5. Update gitlab-shell to the corresponding version
+
+```bash
+cd /home/git/gitlab-shell
+
+sudo -u git -H git fetch --all --tags
+sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION` -b v`cat /home/git/gitlab/GITLAB_SHELL_VERSION`
+sudo -u git -H sh -c 'if [ -x bin/compile ]; then bin/compile; fi'
```
### 6. Start application
@@ -84,6 +90,8 @@ sudo service nginx restart
Check if GitLab and its environment are configured correctly:
```bash
+cd /home/git/gitlab
+
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
```
diff --git a/doc/update/upgrader.md b/doc/update/upgrader.md
index 5fa39ef1b0a..eb7f14a96d5 100644
--- a/doc/update/upgrader.md
+++ b/doc/update/upgrader.md
@@ -60,6 +60,7 @@ GitLab Shell might be outdated, running the commands below ensures you're using
cd /home/git/gitlab-shell
sudo -u git -H git fetch
sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION`
+sudo -u git -H sh -c 'if [ -x bin/compile ] ; then bin/compile ; fi'
```
## One line upgrade command
@@ -78,6 +79,7 @@ cd /home/git/gitlab; \
cd /home/git/gitlab-shell; \
sudo -u git -H git fetch; \
sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION`; \
+ sudo -u git -H sh -c 'if [ -x bin/compile ] ; then bin/compile ; fi'; \
cd /home/git/gitlab; \
sudo service gitlab start; \
sudo service nginx restart; \
diff --git a/doc/update/upgrading_postgresql_using_slony.md b/doc/update/upgrading_postgresql_using_slony.md
new file mode 100644
index 00000000000..f009906256e
--- /dev/null
+++ b/doc/update/upgrading_postgresql_using_slony.md
@@ -0,0 +1,482 @@
+# Upgrading PostgreSQL Using Slony
+
+This guide describes the steps one can take to upgrade their PostgreSQL database
+to the latest version without the need for hours of downtime. This guide assumes
+you have two database servers: one database server running an older version of
+PostgreSQL (e.g. 9.2.18) and one server running a newer version (e.g. 9.6.0).
+
+For this process we'll use a PostgreSQL replication tool called
+["Slony"](http://www.slony.info/). Slony allows replication between different
+PostgreSQL versions and as such can be used to upgrade a cluster with a minimal
+amount of downtime.
+
+In various places we'll refer to the user `gitlab-psql`. This user should be the
+user used to run the various PostgreSQL OS processes. If you're using a
+different user (e.g. `postgres`) you should replace `gitlab-psql` with the name
+of said user. This guide also assumes your database is called
+`gitlabhq_production`. If you happen to use a different database name you should
+change this accordingly.
+
+## Database Dumps
+
+Slony only replicates data and not any schema changes. As a result we must
+ensure that all databases have the same database structure.
+
+To do so we'll generate a dump of our current database. This dump will only
+contain the structure, not any data. To generate this dump run the following
+command on your active database server:
+
+```bash
+sudo -u gitlab-psql /opt/gitlab/embedded/bin/pg_dump -h /var/opt/gitlab/postgresql -p 5432 -U gitlab-psql -s -f /tmp/structure.sql gitlabhq_production
+```
+
+If you're not using GitLab's Omnibus package you may have to adjust the paths to
+`pg_dump` and the PostgreSQL installation directory to match the paths of your
+configuration.
+
+Once the structure dump is generated we also need to generate a dump for the
+`schema_migrations` table. This table doesn't have any primary keys and as such
+can't be replicated easily by Slony. To generate this dump run the following
+command on your active database server:
+
+```bash
+sudo -u gitlab-psql /opt/gitlab/embedded/bin/pg_dump -h /var/opt/gitlab/postgresql/ -p 5432 -U gitlab-psql -a -t schema_migrations -f /tmp/migrations.sql gitlabhq_production
+```
+
+Next we'll need to move these files somewhere accessible by the new database
+server. The easiest way is to simply download these files to your local system:
+
+```bash
+scp your-user@production-database-host:/tmp/*.sql /tmp
+```
+
+This will copy all the SQL files located in `/tmp` to your local system's
+`/tmp` directory. Once copied you can safely remove the files from the database
+server.
+
+## Installing Slony
+
+Slony will be used to upgrade the database without requiring long downtimes.
+Slony can be downloaded from http://www.slony.info/. If you have installed
+PostgreSQL using your operating system's package manager you may also be able to
+install Slony using said package manager.
+
+When compiling Slony from source you *must* use the following commands to do so:
+
+```bash
+./configure --prefix=/path/to/installation/directory --with-perltools --with-pgconfigdir=/path/to/directory/containing/pg_config/bin
+make
+make install
+```
+
+Omnibus users can use the following commands:
+
+```bash
+./configure --prefix=/opt/gitlab/embedded --with-perltools --with-pgconfigdir=/opt/gitlab/embedded/bin
+make
+make install
+```
+
+This assumes you have installed GitLab into /opt/gitlab.
+
+To test if Slony is installed properly, run the following commands:
+
+```bash
+test -f /opt/gitlab/embedded/bin/slonik && echo 'Slony installed' || echo 'Slony not installed'
+test -f /opt/gitlab/embedded/bin/slonik_init_cluster && echo 'Slony Perl tools are available' || echo 'Slony Perl tools are not available'
+/opt/gitlab/embedded/bin/slonik -v
+```
+
+This assumes Slony was installed to `/opt/gitlab/embedded`. If Slony was
+installed properly the output of these commands will be (the mentioned "slonik"
+version may be different):
+
+```
+Slony installed
+Slony Perl tools are available
+slonik version 2.2.5
+```
+
+## Slony User
+
+Next we must set up a PostgreSQL user that Slony can use to replicate your
+database. To do so, log in to your production database using `psql` using a
+super user account. Once done run the following SQL queries:
+
+```sql
+CREATE ROLE slony WITH SUPERUSER LOGIN REPLICATION ENCRYPTED PASSWORD 'password string here';
+ALTER ROLE slony SET statement_timeout TO 0;
+```
+
+Make sure you replace "password string here" with the actual password for the
+user. A password is *required*. This user must be created on _both_ the old and
+new database server using the same password.
+
+Once the user has been created make sure you note down the password as we will
+need it later on.
+
+## Configuring Slony
+
+Now we can finally start configuring Slony. Slony uses a configuration file for
+most of the work so we'll need to set this one up. This configuration file
+specifies where to put log files, how Slony should connect to the databases,
+etc.
+
+First we'll need to create some required directories and set the correct
+permissions. To do so, run the following commands on both the old and new
+database server:
+
+```bash
+sudo mkdir -p /var/log/gitlab/slony /var/run/slony1 /var/opt/gitlab/postgresql/slony
+sudo chown gitlab-psql:root /var/log/gitlab/slony /var/run/slony1 /var/opt/gitlab/postgresql/slony
+```
+
+Here `gitlab-psql` is the user used to run the PostgreSQL database processes. If
+you're using a different user you should replace this with the name of said
+user.
+
+Now that the directories are in place we can create the configuration file. For
+this we can use the following template:
+
+```perl
+if ($ENV{"SLONYNODES"}) {
+ require $ENV{"SLONYNODES"};
+} else {
+ $CLUSTER_NAME = 'slony_replication';
+ $LOGDIR = '/var/log/gitlab/slony';
+ $MASTERNODE = 1;
+ $DEBUGLEVEL = 2;
+
+ add_node(host => 'OLD_HOST', dbname => 'gitlabhq_production', port =>5432,
+ user=>'slony', password=>'SLONY_PASSWORD', node=>1);
+
+ add_node(host => 'NEW_HOST', dbname => 'gitlabhq_production', port =>5432,
+ user=>'slony', password=>'SLONY_PASSWORD', node=>2, parent=>1 );
+}
+
+$SLONY_SETS = {
+ "set1" => {
+ "set_id" => 1,
+ "table_id" => 1,
+ "sequence_id" => 1,
+ "pkeyedtables" => [
+ TABLES
+ ],
+ },
+};
+
+if ($ENV{"SLONYSET"}) {
+ require $ENV{"SLONYSET"};
+}
+
+# Please do not add or change anything below this point.
+1;
+```
+
+In this configuration file you should replace a few placeholders before you can
+use it. The following placeholders should be replaced:
+
+* `OLD_HOST`: the address of the old database server.
+* `NEW_HOST`: the address of the new database server.
+* `SLONY_PASSWORD`: the password of the Slony user created earlier.
+* `TABLES`: the tables to replicate.
+
+The list of tables to replicate can be generated by running the following
+command on your old PostgreSQL database:
+
+```
+sudo gitlab-psql gitlabhq_production -c "select concat('\"', schemaname, '.', tablename, '\",') from pg_catalog.pg_tables where schemaname = 'public' and tableowner = 'gitlab' and tablename != 'schema_migrations' order by tablename asc;" -t
+```
+
+If you're not using Omnibus you should replace `gitlab-psql` with the
+appropriate path to the `psql` executable.
+
+The above command outputs a list of tables in a format that can be copy-pasted
+directly into the above configuration file. Make sure to _replace_ `TABLES` with
+this output, don't just append it below it. Once done you'll end up with
+something like this:
+
+```perl
+"pkeyedtables" => [
+ "public.abuse_reports",
+ "public.appearances",
+ "public.application_settings",
+ ... more rows here ...
+]
+```
+
+Once you have the configuration file generated you must install it on both the
+old and new database. To do so, place it in
+`/var/opt/gitlab/postgresql/slony/slon_tools.conf` (for which we created the
+directory earlier on).
+
+Now that the configuration file is in place we can _finally_ start replicating
+our database. First we must set up the schema in our new database. To do so make
+sure that the SQL files we generated earlier can be found in the `/tmp`
+directory of the new server. Once these files are in place start a `psql`
+session on this server:
+
+```
+sudo gitlab-psql gitlabhq_production
+```
+
+Now run the following commands:
+
+```
+\i /tmp/structure.sql
+\i /tmp/migrations.sql
+```
+
+To verify if the structure is in place close the session, start it again, then
+run `\d`. If all went well you should see output along the lines of the
+following:
+
+```
+ List of relations
+ Schema | Name | Type | Owner
+--------+---------------------------------------------+----------+-------------
+ public | abuse_reports | table | gitlab
+ public | abuse_reports_id_seq | sequence | gitlab
+ public | appearances | table | gitlab
+ public | appearances_id_seq | sequence | gitlab
+ public | application_settings | table | gitlab
+ public | application_settings_id_seq | sequence | gitlab
+ public | approvals | table | gitlab
+ ... more rows here ...
+```
+
+Now we can initialize the required tables and what not that Slony will use for
+its replication process. To do so, run the following on the old database:
+
+```
+sudo -u gitlab-psql /opt/gitlab/embedded/bin/slonik_init_cluster --conf /var/opt/gitlab/postgresql/slony/slon_tools.conf | /opt/gitlab/embedded/bin/slonik
+```
+
+If all went well this will produce something along the lines of:
+
+```
+<stdin>:10: Set up replication nodes
+<stdin>:13: Next: configure paths for each node/origin
+<stdin>:16: Replication nodes prepared
+<stdin>:17: Please start a slon replication daemon for each node
+```
+
+Next we need to start a replication node on every server. To do so, run the
+following on the old database:
+
+```
+sudo -u gitlab-psql /opt/gitlab/embedded/bin/slon_start 1 --conf /var/opt/gitlab/postgresql/slony/slon_tools.conf
+```
+
+If all went well this will produce output such as:
+
+
+```
+Invoke slon for node 1 - /opt/gitlab/embedded/bin/slon -p /var/run/slony1/slony_replication_node1.pid -s 1000 -d2 slony_replication 'host=192.168.0.7 dbname=gitlabhq_production user=slony port=5432 password=hieng8ezohHuCeiqu0leeghai4aeyahp' > /var/log/gitlab/slony/node1/gitlabhq_production-2016-10-06.log 2>&1 &
+Slon successfully started for cluster slony_replication, node node1
+PID [26740]
+Start the watchdog process as well...
+```
+
+Next we need to run the following command on the _new_ database server:
+
+```
+sudo -u gitlab-psql /opt/gitlab/embedded/bin/slon_start 2 --conf /var/opt/gitlab/postgresql/slony/slon_tools.conf
+```
+
+This will produce similar output if all went well.
+
+Next we need to tell the new database server what it should replicate. This can
+be done by running the following command on the _new_ database server:
+
+```
+sudo -u gitlab-psql /opt/gitlab/embedded/bin/slonik_create_set 1 --conf /var/opt/gitlab/postgresql/slony/slon_tools.conf | /opt/gitlab/embedded/bin/slonik
+```
+
+This should produce output along the lines of the following:
+
+```
+<stdin>:11: Subscription set 1 (set1) created
+<stdin>:12: Adding tables to the subscription set
+<stdin>:16: Add primary keyed table public.abuse_reports
+<stdin>:20: Add primary keyed table public.appearances
+<stdin>:24: Add primary keyed table public.application_settings
+... more rows here ...
+<stdin>:327: Adding sequences to the subscription set
+<stdin>:328: All tables added
+```
+
+Finally we can start the replication process by running the following on the
+_new_ database server:
+
+```
+sudo -u gitlab-psql /opt/gitlab/embedded/bin/slonik_subscribe_set 1 2 --conf /var/opt/gitlab/postgresql/slony/slon_tools.conf | /opt/gitlab/embedded/bin/slonik
+```
+
+This should produce the following output:
+
+```
+<stdin>:6: Subscribed nodes to set 1
+```
+
+At this point the new database server will start replicating the data of the old
+database server. This process can take anywhere from a few minutes to hours, if
+not days. Unfortunately Slony itself doesn't really provide a way of knowing
+when the two databases are in sync. To get an estimate of the progress you can
+use the following shell script:
+
+```
+#!/usr/bin/env bash
+
+set -e
+
+user='slony'
+pass='SLONY_PASSWORD'
+
+function main {
+ while :
+ do
+ local source
+ local target
+
+ source=$(PGUSER="${user}" PGPASSWORD="${pass}" /opt/gitlab/embedded/bin/psql -h OLD_HOST gitlabhq_production -c "select pg_size_pretty(pg_database_size('gitlabhq_production'));" -t -A)
+ target=$(PGUSER="${user}" PGPASSWORD="${pass}" /opt/gitlab/embedded/bin/psql -h NEW_HOST gitlabhq_production -c "select pg_size_pretty(pg_database_size('gitlabhq_production'));" -t -A)
+
+ echo "$(date): ${target} of ${source}" >> progress.log
+ echo "$(date): ${target} of ${source}"
+
+ sleep 60
+ done
+}
+
+main
+```
+
+This script will compare the sizes of the old and new database every minute and
+print the result to STDOUT as well as logging it to a file. Make sure to replace
+`SLONY_PASSWORD`, `OLD_HOST`, and `NEW_HOST` with the correct values.
+
+## Stopping Replication
+
+At some point the two databases are in sync. Once this is the case you'll need
+to plan for a few minutes of downtime. This small downtime window is used to
+stop the replication process, remove any Slony data from both databases, restart
+GitLab so it can use the new database, etc.
+
+First, let's stop all of GitLab. Omnibus users can do so by running the
+following on their GitLab server(s):
+
+```
+sudo gitlab-ctl stop unicorn
+sudo gitlab-ctl stop sidekiq
+sudo gitlab-ctl stop mailroom
+```
+
+If you have any other processes that use PostgreSQL you should also stop those.
+
+Once everything has been stopped you should update any configuration settings,
+DNS records, etc so they all point to the new database.
+
+Once the settings have been taken care of we need to stop the replication
+process. It's crucial that no new data is written to the databases at this point
+as this data will be lost.
+
+To stop replication, run the following on both database servers:
+
+```bash
+sudo -u gitlab-psql /opt/gitlab/embedded/bin/slon_kill --conf /var/opt/gitlab/postgresql/slony/slon_tools.conf
+```
+
+This will stop all the Slony processes on the host the command was executed on.
+
+## Resetting Sequences
+
+The above setup does not replicate database sequences, as such these must be
+reset manually in the target database. You can use the following script for
+this:
+
+```bash
+#!/usr/bin/env bash
+set -e
+
+function main {
+ local fix_sequences
+ local fix_owners
+
+ fix_sequences='/tmp/fix_sequences.sql'
+ fix_owners='/tmp/fix_owners.sql'
+
+ # The SQL queries were taken from
+ # https://wiki.postgresql.org/wiki/Fixing_Sequences
+ sudo gitlab-psql gitlabhq_production -t -c "
+ SELECT 'ALTER SEQUENCE '|| quote_ident(MIN(schema_name)) ||'.'|| quote_ident(MIN(seq_name))
+ ||' OWNED BY '|| quote_ident(MIN(TABLE_NAME)) ||'.'|| quote_ident(MIN(column_name)) ||';'
+ FROM (
+ SELECT
+ n.nspname AS schema_name,
+ c.relname AS TABLE_NAME,
+ a.attname AS column_name,
+ SUBSTRING(d.adsrc FROM E'^nextval\\(''([^'']*)''(?:::text|::regclass)?\\)') AS seq_name
+ FROM pg_class c
+ JOIN pg_attribute a ON (c.oid=a.attrelid)
+ JOIN pg_attrdef d ON (a.attrelid=d.adrelid AND a.attnum=d.adnum)
+ JOIN pg_namespace n ON (c.relnamespace=n.oid)
+ WHERE has_schema_privilege(n.oid,'USAGE')
+ AND n.nspname NOT LIKE 'pg!_%' escape '!'
+ AND has_table_privilege(c.oid,'SELECT')
+ AND (NOT a.attisdropped)
+ AND d.adsrc ~ '^nextval'
+ ) seq
+ GROUP BY seq_name HAVING COUNT(*)=1;
+ " > "${fix_owners}"
+
+ sudo gitlab-psql gitlabhq_production -t -c "
+ SELECT 'SELECT SETVAL(' ||
+ quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||
+ ', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1) ) FROM ' ||
+ quote_ident(PGT.schemaname)|| '.'||quote_ident(T.relname)|| ';'
+ FROM pg_class AS S,
+ pg_depend AS D,
+ pg_class AS T,
+ pg_attribute AS C,
+ pg_tables AS PGT
+ WHERE S.relkind = 'S'
+ AND S.oid = D.objid
+ AND D.refobjid = T.oid
+ AND D.refobjid = C.attrelid
+ AND D.refobjsubid = C.attnum
+ AND T.relname = PGT.tablename
+ ORDER BY S.relname;
+ " > "${fix_sequences}"
+
+ sudo gitlab-psql gitlabhq_production -f "${fix_owners}"
+ sudo gitlab-psql gitlabhq_production -f "${fix_sequences}"
+
+ rm "${fix_owners}" "${fix_sequences}"
+}
+
+main
+```
+
+Upload this script to the _target_ server and execute it as follows:
+
+```bash
+bash path/to/the/script/above.sh
+```
+
+This will correct the ownership of sequences and reset the next value for the
+`id` column to the next available value.
+
+## Removing Slony
+
+Next we need to remove all Slony related data. To do so, run the following
+command on the _target_ server:
+
+```bash
+sudo gitlab-psql gitlabhq_production -c "DROP SCHEMA _slony_replication CASCADE;"
+```
+
+Once done you can safely remove any Slony related files (e.g. the log
+directory), and uninstall Slony if desired. At this point you can start your
+GitLab instance again and if all went well it should be using your new database
+server.
diff --git a/doc/user/account/security.md b/doc/user/account/security.md
index 816094bf8d2..f4078876fab 100644
--- a/doc/user/account/security.md
+++ b/doc/user/account/security.md
@@ -1,3 +1 @@
-# Account Security
-
-- [Two-Factor Authentication](two_factor_authentication.md)
+This document was moved to [profile](../profile/account/index.md).
diff --git a/doc/user/account/two_factor_authentication.md b/doc/user/account/two_factor_authentication.md
index 881358ed94d..ea2c8307860 100644
--- a/doc/user/account/two_factor_authentication.md
+++ b/doc/user/account/two_factor_authentication.md
@@ -1,68 +1 @@
-# Two-Factor Authentication
-
-## Recovery options
-
-If you lose your code generation device (such as your mobile phone) and you need
-to disable two-factor authentication on your account, you have several options.
-
-### Use a saved recovery code
-
-When you enabled two-factor authentication for your account, a series of
-recovery codes were generated. If you saved those codes somewhere safe, you
-may use one to sign in.
-
-First, enter your username/email and password on the GitLab sign in page. When
-prompted for a two-factor code, enter one of the recovery codes you saved
-previously.
-
-> **Note:** Once a particular recovery code has been used, it cannot be used again.
- You may still use the other saved recovery codes at a later time.
-
-### Generate new recovery codes using SSH
-
-It's not uncommon for users to forget to save the recovery codes when enabling
-two-factor authentication. If you have an SSH key added to your GitLab account,
-you can generate a new set of recovery codes using SSH.
-
-Run `ssh git@gitlab.example.com 2fa_recovery_codes`. You will be prompted to
-confirm that you wish to generate new codes. If you choose to continue, any
-previously saved codes will be invalidated.
-
-```bash
-$ ssh git@gitlab.example.com 2fa_recovery_codes
-Are you sure you want to generate new two-factor recovery codes?
-Any existing recovery codes you saved will be invalidated. (yes/no)
-yes
-
-Your two-factor authentication recovery codes are:
-
-119135e5a3ebce8e
-11f6v2a498810dcd
-3924c7ab2089c902
-e79a3398bfe4f224
-34bd7b74adbc8861
-f061691d5107df1a
-169bf32a18e63e7f
-b510e7422e81c947
-20dbed24c5e74663
-df9d3b9403b9c9f0
-
-During sign in, use one of the codes above when prompted for
-your two-factor code. Then, visit your Profile Settings and add
-a new device so you do not lose access to your account again.
-```
-
-Next, go to the GitLab sign in page and enter your username/email and password.
-When prompted for a two-factor code, enter one of the recovery codes obtained
-from the command line output.
-
-> **Note:** After signing in, you should immediately visit your **Profile Settings
- -> Account** to set up two-factor authentication with a new device.
-
-### Ask a GitLab administrator to disable two-factor on your account
-
-If the above two methods are not possible, you may ask a GitLab global
-administrator to disable two-factor authentication for your account. Please
-be aware that this will temporarily leave your account in a less secure state.
-You should sign in and re-enable two-factor authentication as soon as possible
-after the administrator disables it.
+This document was moved to [profile/account/two_factor_authentication](../profile/account/two_factor_authentication.md).
diff --git a/doc/user/admin_area/img/admin_labels.png b/doc/user/admin_area/img/admin_labels.png
index 1ee33a534ab..a9ea059ccf9 100644
--- a/doc/user/admin_area/img/admin_labels.png
+++ b/doc/user/admin_area/img/admin_labels.png
Binary files differ
diff --git a/doc/user/admin_area/img/cohorts.png b/doc/user/admin_area/img/cohorts.png
new file mode 100644
index 00000000000..8bae7faff07
--- /dev/null
+++ b/doc/user/admin_area/img/cohorts.png
Binary files differ
diff --git a/doc/user/admin_area/monitoring/convdev.md b/doc/user/admin_area/monitoring/convdev.md
new file mode 100644
index 00000000000..3d93c7557a4
--- /dev/null
+++ b/doc/user/admin_area/monitoring/convdev.md
@@ -0,0 +1,29 @@
+# Conversational Development Index
+
+> [Introduced][ce-30469] in GitLab 9.3.
+
+Conversational Development Index (ConvDev) gives you an overview of your entire
+instance's feature usage, from idea to production. It looks at your usage in the
+past 30 days, averaged over the number of active users in that time period. It also
+provides a lead score per feature, which is calculated based on GitLab's analysis
+of top performing instances, based on [usage ping data][ping] that GitLab has
+collected. Your score is compared to the lead score, expressed as a percentage.
+The overall index score is an average over all your feature scores.
+
+![ConvDev index](img/convdev_index.png)
+
+The page also provides helpful links to articles and GitLab docs, to help you
+improve your scores.
+
+Your GitLab instance's usage ping must be activated in order to use this feature.
+Usage ping data is aggregated on GitLab's servers for analysis. Your usage
+information is **not sent** to any other GitLab instances.
+
+If you have just started using GitLab, it may take a few weeks for data to be
+collected before this feature is available.
+
+This feature is accessible only to a system admin, at
+**Admin area > Monitoring > ConvDev Index**.
+
+[ce-30469]: https://gitlab.com/gitlab-org/gitlab-ce/issues/30469
+[ping]: ../settings/usage_statistics.md#usage-ping
diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md
new file mode 100644
index 00000000000..a954840b8a6
--- /dev/null
+++ b/doc/user/admin_area/monitoring/health_check.md
@@ -0,0 +1,108 @@
+# Health Check
+
+>**Notes:**
+ - Liveness and readiness probes were [introduced][ce-10416] in GitLab 9.1.
+ - The `health_check` endpoint was [introduced][ce-3888] in GitLab 8.8 and will
+ be deprecated in GitLab 9.1. Read more in the [old behavior](#old-behavior)
+ section.
+
+GitLab provides liveness and readiness probes to indicate service health and
+reachability to required services. These probes report on the status of the
+database connection, Redis connection, and access to the filesystem. These
+endpoints [can be provided to schedulers like Kubernetes][kubernetes] to hold
+traffic until the system is ready or restart the container as needed.
+
+## Access Token
+
+An access token needs to be provided while accessing the probe endpoints. The current
+accepted token can be found under the **Admin area ➔ Monitoring ➔ Health check**
+(`admin/health_check`) page of your GitLab instance.
+
+![access token](img/health_check_token.png)
+
+The access token can be passed as a URL parameter:
+
+```
+https://gitlab.example.com/-/readiness?token=ACCESS_TOKEN
+```
+
+which will then provide a report of system health in JSON format:
+
+```
+{
+ "db_check": {
+ "status": "ok"
+ },
+ "redis_check": {
+ "status": "ok"
+ },
+ "fs_shards_check": {
+ "status": "ok",
+ "labels": {
+ "shard": "default"
+ }
+ }
+}
+```
+
+## Using the Endpoint
+
+Once you have the access token, the probes can be accessed:
+
+- `https://gitlab.example.com/-/readiness?token=ACCESS_TOKEN`
+- `https://gitlab.example.com/-/liveness?token=ACCESS_TOKEN`
+
+## Status
+
+On failure, the endpoint will return a `500` HTTP status code. On success, the endpoint
+will return a valid successful HTTP status code, and a `success` message.
+
+## Old behavior
+
+>**Notes:**
+ - Liveness and readiness probes were [introduced][ce-10416] in GitLab 9.1.
+ - The `health_check` endpoint was [introduced][ce-3888] in GitLab 8.8 and will
+ be deprecated in GitLab 9.1. Read more in the [old behavior](#old-behavior)
+ section.
+
+GitLab provides a health check endpoint for uptime monitoring on the `health_check` web
+endpoint. The health check reports on the overall system status based on the status of
+the database connection, the state of the database migrations, and the ability to write
+and access the cache. This endpoint can be provided to uptime monitoring services like
+[Pingdom][pingdom], [Nagios][nagios-health], and [NewRelic][newrelic-health].
+
+Once you have the [access token](#access-token), health information can be
+retrieved as plain text, JSON, or XML using the `health_check` endpoint:
+
+- `https://gitlab.example.com/health_check?token=ACCESS_TOKEN`
+- `https://gitlab.example.com/health_check.json?token=ACCESS_TOKEN`
+- `https://gitlab.example.com/health_check.xml?token=ACCESS_TOKEN`
+
+You can also ask for the status of specific services:
+
+- `https://gitlab.example.com/health_check/cache.json?token=ACCESS_TOKEN`
+- `https://gitlab.example.com/health_check/database.json?token=ACCESS_TOKEN`
+- `https://gitlab.example.com/health_check/migrations.json?token=ACCESS_TOKEN`
+
+For example, the JSON output of the following health check:
+
+```bash
+curl --header "TOKEN: ACCESS_TOKEN" https://gitlab.example.com/health_check.json
+```
+
+would be like:
+
+```
+{"healthy":true,"message":"success"}
+```
+
+On failure, the endpoint will return a `500` HTTP status code. On success, the endpoint
+will return a valid successful HTTP status code, and a `success` message. Ideally your
+uptime monitoring should look for the success message.
+
+[ce-10416]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10416
+[ce-3888]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3888
+[pingdom]: https://www.pingdom.com
+[nagios-health]: https://nagios-plugins.org/doc/man/check_http.html
+[newrelic-health]: https://docs.newrelic.com/docs/alerts/alert-policies/downtime-alerts/availability-monitoring
+[kubernetes]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/
diff --git a/doc/user/admin_area/monitoring/img/convdev_index.png b/doc/user/admin_area/monitoring/img/convdev_index.png
new file mode 100644
index 00000000000..4e47ff2228d
--- /dev/null
+++ b/doc/user/admin_area/monitoring/img/convdev_index.png
Binary files differ
diff --git a/doc/user/admin_area/monitoring/img/health_check_token.png b/doc/user/admin_area/monitoring/img/health_check_token.png
new file mode 100644
index 00000000000..182549fc484
--- /dev/null
+++ b/doc/user/admin_area/monitoring/img/health_check_token.png
Binary files differ
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index 34e2e557f89..eb6f915f3f4 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -2,19 +2,37 @@
## Maximum artifacts size
-The maximum size of the [build artifacts][art-yml] can be set in the Admin area
-of your GitLab instance. The value is in MB and the default is 100MB. Note that
-this setting is set for each build.
+The maximum size of the [job artifacts][art-yml] can be set in the Admin area
+of your GitLab instance. The value is in *MB* and the default is 100MB. Note
+that this setting is set for each job.
1. Go to **Admin area > Settings** (`/admin/application_settings`).
![Admin area settings button](img/admin_area_settings_button.png)
-1. Change the value of the maximum artifacts size (in MB):
+1. Change the value of maximum artifacts size (in MB):
![Admin area maximum artifacts size](img/admin_area_maximum_artifacts_size.png)
1. Hit **Save** for the changes to take effect.
+## Default artifacts expiration
-[art-yml]: ../../../administration/build_artifacts.md
+The default expiration time of the [job artifacts][art-yml] can be set in
+the Admin area of your GitLab instance. The syntax of duration is described
+in [artifacts:expire_in][duration-syntax]. The default is `30 days`. Note that
+this setting is set for each job. Set it to 0 if you don't want default
+expiration.
+
+1. Go to **Admin area > Settings** (`/admin/application_settings`).
+
+ ![Admin area settings button](img/admin_area_settings_button.png)
+
+1. Change the value of default expiration time ([syntax][duration-syntax]):
+
+ ![Admin area default artifacts expiration](img/admin_area_default_artifacts_expiration.png)
+
+1. Hit **Save** for the changes to take effect.
+
+[art-yml]: ../../../administration/job_artifacts.md
+[duration-syntax]: ../../../ci/yaml/README.md#artifactsexpire_in
diff --git a/doc/user/admin_area/settings/img/access_restrictions.png b/doc/user/admin_area/settings/img/access_restrictions.png
index 8eea84320d7..8c5336c7835 100644
--- a/doc/user/admin_area/settings/img/access_restrictions.png
+++ b/doc/user/admin_area/settings/img/access_restrictions.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/admin_area_default_artifacts_expiration.png b/doc/user/admin_area/settings/img/admin_area_default_artifacts_expiration.png
new file mode 100644
index 00000000000..50a86ede56b
--- /dev/null
+++ b/doc/user/admin_area/settings/img/admin_area_default_artifacts_expiration.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/admin_area_maximum_artifacts_size.png b/doc/user/admin_area/settings/img/admin_area_maximum_artifacts_size.png
index 53f7e76033e..33fd29e2039 100644
--- a/doc/user/admin_area/settings/img/admin_area_maximum_artifacts_size.png
+++ b/doc/user/admin_area/settings/img/admin_area_maximum_artifacts_size.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/admin_area_settings_button.png b/doc/user/admin_area/settings/img/admin_area_settings_button.png
index 509708b627f..1d2c0ac04bc 100644
--- a/doc/user/admin_area/settings/img/admin_area_settings_button.png
+++ b/doc/user/admin_area/settings/img/admin_area_settings_button.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/domain_blacklist.png b/doc/user/admin_area/settings/img/domain_blacklist.png
index bd87b73cf9e..dedd3be1e8f 100644
--- a/doc/user/admin_area/settings/img/domain_blacklist.png
+++ b/doc/user/admin_area/settings/img/domain_blacklist.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/restricted_url.png b/doc/user/admin_area/settings/img/restricted_url.png
index 8b00a18320b..67abd13f741 100644
--- a/doc/user/admin_area/settings/img/restricted_url.png
+++ b/doc/user/admin_area/settings/img/restricted_url.png
Binary files differ
diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md
index 4b540473a6e..603b826e7f2 100644
--- a/doc/user/admin_area/settings/sign_up_restrictions.md
+++ b/doc/user/admin_area/settings/sign_up_restrictions.md
@@ -1,5 +1,20 @@
# Sign-up restrictions
+You can block email addresses of specific domains, or whitelist only some
+specifc domains via the **Application Settings** in the Admin area.
+
+>**Note**: These restrictions are only applied during sign-up. An admin is
+able to add add a user through the admin panel with a disallowed domain. Also
+note that the users can change their email addresses after signup to
+disallowed domains.
+
+## Whitelist email domains
+
+> [Introduced][ce-598] in GitLab 7.11.0
+
+You can restrict users to only signup using email addresses matching the given
+domains list.
+
## Blacklist email domains
> [Introduced][ce-5259] in GitLab 8.10.
@@ -9,13 +24,16 @@ from creating an account on your GitLab server. This is particularly useful to
prevent spam. Disposable email addresses are usually used by malicious users to
create dummy accounts and spam issues.
+## Settings
+
This feature can be activated via the **Application Settings** in the Admin area,
and you have the option of entering the list manually, or uploading a file with
the list.
-The blacklist accepts wildcards, so you can use `*.test.com` to block every
-`test.com` subdomain, or `*.io` to block all domains ending in `.io`. Domains
-should be separated by a whitespace, semicolon, comma, or a new line.
+Both whitelist and blacklist accept wildcards, so for example, you can use
+`*.company.com` to accept every `company.com` subdomain, or `*.io` to block all
+domains ending in `.io`. Domains should be separated by a whitespace,
+semicolon, comma, or a new line.
![Domain Blacklist](img/domain_blacklist.png)
diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md
new file mode 100644
index 00000000000..d874688cc29
--- /dev/null
+++ b/doc/user/admin_area/settings/usage_statistics.md
@@ -0,0 +1,66 @@
+# Usage statistics
+
+GitLab Inc. will periodically collect information about your instance in order
+to perform various actions.
+
+All statistics are opt-out, you can enable/disable them from the admin panel
+under **Admin area > Settings > Usage statistics**.
+
+## Version check
+
+GitLab can inform you when an update is available and the importance of it.
+
+No information other than the GitLab version and the instance's hostname (through the HTTP referer)
+are collected.
+
+In the **Overview** tab you can see if your GitLab version is up to date. There
+are three cases: 1) you are up to date (green), 2) there is an update available
+(yellow) and 3) your version is vulnerable and a security fix is released (red).
+
+In any case, you will see a message informing you of the state and the
+importance of the update.
+
+If enabled, the version status will also be shown in the help page (`/help`)
+for all signed in users.
+
+## Usage ping
+
+> [Introduced][ee-557] in GitLab Enterprise Edition 8.10. More statistics
+[were added][ee-735] in GitLab Enterprise Edition
+8.12. [Moved to GitLab Community Edition][ce-23361] in 9.1.
+
+GitLab sends a weekly payload containing usage data to GitLab Inc. The usage
+ping uses high-level data to help our product, support, and sales teams. It does
+not send any project names, usernames, or any other specific data. The
+information from the usage ping is not anonymous, it is linked to the hostname
+of the instance.
+
+You can view the exact JSON payload in the administration panel.
+
+### Deactivate the usage ping
+
+The usage ping is opt-out. If you want to deactivate this feature, go to
+the Settings page of your administration panel and uncheck the Usage ping
+checkbox.
+
+To disable the usage ping and prevent it from being configured in future through
+the administration panel, Omnibus installs can set the following in
+[`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html#configuration-options):
+
+```ruby
+gitlab_rails['usage_ping_enabled'] = false
+```
+
+And source installs can set the following in `gitlab.yml`:
+
+```yaml
+production: &base
+ # ...
+ gitlab:
+ # ...
+ usage_ping_enabled: false
+```
+
+[ee-557]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/557
+[ee-735]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/735
+[ce-23361]: https://gitlab.com/gitlab-org/gitlab-ce/issues/23361
diff --git a/doc/user/admin_area/user_cohorts.md b/doc/user/admin_area/user_cohorts.md
new file mode 100644
index 00000000000..e25e7a8bbc3
--- /dev/null
+++ b/doc/user/admin_area/user_cohorts.md
@@ -0,0 +1,37 @@
+# Cohorts
+
+> **Notes:**
+> [Introduced][ce-23361] in GitLab 9.1.
+
+As a benefit of having the [usage ping active](settings/usage_statistics.md),
+GitLab lets you analyze the users' activities of your GitLab installation.
+Under `/admin/cohorts`, when the usage ping is active, GitLab will show the
+monthly cohorts of new users and their activities over time.
+
+## Overview
+
+How do we read the user cohorts table? Let's take an example with the following
+user cohorts.
+
+![User cohort example](img/cohorts.png)
+
+For the cohort of June 2016, 163 users have been added on this server and have
+been active since this month. One month later, in July 2016, out of
+these 163 users, 155 users (or 95% of the June cohort) are still active. Two
+months later, 139 users (or 85%) are still active. 9 months later, we can see
+that only 6% of this cohort are still active.
+
+The Inactive users column shows the number of users who have been added during
+the month, but who have never actually had any activity in the instance.
+
+How do we measure the activity of users? GitLab considers a user active if:
+
+* the user signs in
+* the user has Git activity (whether push or pull).
+
+## Setup
+
+1. [Activate the usage ping](settings/usage_statistics.md)
+2. Go to `/admin/cohorts` to see the user cohorts of the server
+
+[ce-23361]: https://gitlab.com/gitlab-org/gitlab-ce/issues/23361
diff --git a/doc/user/award_emojis.md b/doc/user/award_emojis.md
new file mode 100644
index 00000000000..acbd2a66d37
--- /dev/null
+++ b/doc/user/award_emojis.md
@@ -0,0 +1,51 @@
+# Award emoji
+
+>**Notes:**
+- First [introduced][1825] in GitLab 8.2.
+- GitLab 9.0 [introduced][ce-9570] the usage of native emojis if the platform
+ supports them and falls back to images or CSS sprites. This change greatly
+ improved the award emoji performance overall.
+
+When you're collaborating online, you get fewer opportunities for high-fives
+and thumbs-ups. Emoji can be awarded to issues, merge requests, snippets, and
+virtually everywhere where you can have a discussion.
+
+![Award emoji](img/award_emoji_select.png)
+
+Award emoji make it much easier to give and receive feedback without a long
+comment thread. Comments that are only emoji will automatically become
+award emoji.
+
+## Sort issues and merge requests on vote count
+
+> [Introduced][2871] in GitLab 8.5.
+
+You can quickly sort issues and merge requests by the number of votes they
+have received. The sort options can be found in the dropdown menu as "Most
+popular" and "Least popular".
+
+![Votes sort options](img/award_emoji_votes_sort_options.png)
+
+The total number of votes is not summed up. An issue with 18 upvotes and 5
+downvotes is considered more popular than an issue with 17 upvotes and no
+downvotes.
+
+## Award emoji for comments
+
+> [Introduced][4291] in GitLab 8.9.
+
+Award emoji can also be applied to individual comments when you want to
+celebrate an accomplishment or agree with an opinion.
+
+To add an award emoji, click the smile in the top right of the comment and pick
+an emoji from the dropdown. If you want to remove an award emoji, just click
+the emoji again and the vote will be removed.
+
+![Picking an emoji for a comment](img/award_emoji_comment_picker.png)
+
+![An award emoji has been applied to a comment](img/award_emoji_comment_awarded.png)
+
+[2871]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2781
+[1825]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/1825
+[4291]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4291
+[ce-9570]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9570
diff --git a/doc/user/discussions/img/btn_new_issue_for_all_discussions.png b/doc/user/discussions/img/btn_new_issue_for_all_discussions.png
new file mode 100644
index 00000000000..b15447ec290
--- /dev/null
+++ b/doc/user/discussions/img/btn_new_issue_for_all_discussions.png
Binary files differ
diff --git a/doc/user/discussions/img/comment_type_toggle.gif b/doc/user/discussions/img/comment_type_toggle.gif
new file mode 100644
index 00000000000..b73c197b97f
--- /dev/null
+++ b/doc/user/discussions/img/comment_type_toggle.gif
Binary files differ
diff --git a/doc/user/discussions/img/discussion_comment.png b/doc/user/discussions/img/discussion_comment.png
new file mode 100644
index 00000000000..8f66d138922
--- /dev/null
+++ b/doc/user/discussions/img/discussion_comment.png
Binary files differ
diff --git a/doc/user/discussions/img/discussion_view.png b/doc/user/discussions/img/discussion_view.png
new file mode 100644
index 00000000000..2ee1db2eab3
--- /dev/null
+++ b/doc/user/discussions/img/discussion_view.png
Binary files differ
diff --git a/doc/user/discussions/img/discussions_resolved.png b/doc/user/discussions/img/discussions_resolved.png
new file mode 100644
index 00000000000..3fd496f6da5
--- /dev/null
+++ b/doc/user/discussions/img/discussions_resolved.png
Binary files differ
diff --git a/doc/user/discussions/img/new_issue_for_discussion.png b/doc/user/discussions/img/new_issue_for_discussion.png
new file mode 100644
index 00000000000..93c9dad8921
--- /dev/null
+++ b/doc/user/discussions/img/new_issue_for_discussion.png
Binary files differ
diff --git a/doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved.png b/doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved.png
new file mode 100644
index 00000000000..928c7d33898
--- /dev/null
+++ b/doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved.png
Binary files differ
diff --git a/doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved_msg.png b/doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved_msg.png
new file mode 100644
index 00000000000..bcdc0250d7c
--- /dev/null
+++ b/doc/user/discussions/img/only_allow_merge_if_all_discussions_are_resolved_msg.png
Binary files differ
diff --git a/doc/user/discussions/img/preview_issue_for_discussion.png b/doc/user/discussions/img/preview_issue_for_discussion.png
new file mode 100644
index 00000000000..2ee0653b2ba
--- /dev/null
+++ b/doc/user/discussions/img/preview_issue_for_discussion.png
Binary files differ
diff --git a/doc/user/discussions/img/preview_issue_for_discussions.png b/doc/user/discussions/img/preview_issue_for_discussions.png
new file mode 100644
index 00000000000..3fe0a666678
--- /dev/null
+++ b/doc/user/discussions/img/preview_issue_for_discussions.png
Binary files differ
diff --git a/doc/user/discussions/img/resolve_comment_button.png b/doc/user/discussions/img/resolve_comment_button.png
new file mode 100644
index 00000000000..70340108874
--- /dev/null
+++ b/doc/user/discussions/img/resolve_comment_button.png
Binary files differ
diff --git a/doc/user/discussions/img/resolve_discussion_button.png b/doc/user/discussions/img/resolve_discussion_button.png
new file mode 100644
index 00000000000..ab454f661e0
--- /dev/null
+++ b/doc/user/discussions/img/resolve_discussion_button.png
Binary files differ
diff --git a/doc/user/discussions/img/resolve_discussion_issue_notice.png b/doc/user/discussions/img/resolve_discussion_issue_notice.png
new file mode 100644
index 00000000000..e0ee6a39ffd
--- /dev/null
+++ b/doc/user/discussions/img/resolve_discussion_issue_notice.png
Binary files differ
diff --git a/doc/user/discussions/img/resolve_discussion_open_issue.png b/doc/user/discussions/img/resolve_discussion_open_issue.png
new file mode 100644
index 00000000000..98d63278326
--- /dev/null
+++ b/doc/user/discussions/img/resolve_discussion_open_issue.png
Binary files differ
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
new file mode 100644
index 00000000000..8b1d299484c
--- /dev/null
+++ b/doc/user/discussions/index.md
@@ -0,0 +1,150 @@
+# Discussions
+
+The ability to contribute conversationally is offered throughout GitLab.
+
+You can leave a comment in the following places:
+
+- issues
+- merge requests
+- snippets
+- commits
+- commit diffs
+
+The comment area supports [Markdown] and [quick actions]. One can edit their
+own comment at any time, and anyone with [Master access level][permissions] or
+higher can also edit a comment made by someone else.
+
+Apart from the standard comments, you also have the option to create a comment
+in the form of a resolvable or threaded discussion.
+
+## Resolvable discussions
+
+>**Notes:**
+- The main feature was [introduced][ce-5022] in GitLab 8.11.
+- Resolvable discussions can be added only to merge request diffs.
+
+Discussion resolution helps keep track of progress during planning or code review.
+Resolving comments prevents you from forgetting to address feedback and lets you
+hide discussions that are no longer relevant.
+
+!["A discussion between two people on a piece of code"][discussion-view]
+
+Comments and discussions can be resolved by anyone with at least Developer
+access to the project or the author of the merge request.
+
+### Jumping between unresolved discussions
+
+When a merge request has a large number of comments it can be difficult to track
+what remains unresolved. You can jump between unresolved discussions with the
+Jump button next to the Reply field on a discussion.
+
+You can also jump to the first unresolved discussion from the button next to the
+resolved discussions tracker.
+
+!["3/4 discussions resolved"][discussions-resolved]
+
+### Marking a comment or discussion as resolved
+
+You can mark a discussion as resolved by clicking the **Resolve discussion**
+button at the bottom of the discussion.
+
+!["Resolve discussion" button][resolve-discussion-button]
+
+Alternatively, you can mark each comment as resolved individually.
+
+!["Resolve comment" button][resolve-comment-button]
+
+### Move all unresolved discussions in a merge request to an issue
+
+> [Introduced][ce-8266] in GitLab 9.1
+
+To continue all open discussions from a merge request in a new issue, click the
+**Resolve all discussions in new issue** button.
+
+![Open new issue for all unresolved discussions](img/btn_new_issue_for_all_discussions.png)
+
+Alternatively, when your project only accepts merge requests [when all discussions
+are resolved](#only-allow-merge-requests-to-be-merged-if-all-discussions-are-resolved),
+there will be an **open an issue to resolve them later** link in the merge
+request widget.
+
+![Link in merge request widget](img/resolve_discussion_open_issue.png)
+
+This will prepare an issue with its content referring to the merge request and
+the unresolved discussions.
+
+![Issue mentioning discussions in a merge request](img/preview_issue_for_discussions.png)
+
+Hitting **Submit issue** will cause all discussions to be marked as resolved and
+add a note referring to the newly created issue.
+
+![Mark discussions as resolved notice](img/resolve_discussion_issue_notice.png)
+
+You can now proceed to merge the merge request from the UI.
+
+### Moving a single discussion to a new issue
+
+> [Introduced][ce-8266] in GitLab 9.1
+
+To create a new issue for a single discussion, you can use the **Resolve this
+discussion in a new issue** button.
+
+![Create issue for discussion](img/new_issue_for_discussion.png)
+
+This will direct you to a new issue prefilled with the content of the
+discussion, similar to the issues created for delegating multiple
+discussions at once. Saving the issue will mark the discussion as resolved and
+add a note to the merge request discussion referencing the new issue.
+
+![New issue for a single discussion](img/preview_issue_for_discussion.png)
+
+### Only allow merge requests to be merged if all discussions are resolved
+
+> [Introduced][ce-7125] in GitLab 8.14.
+
+You can prevent merge requests from being merged until all discussions are
+resolved.
+
+Navigate to your project's settings page, select the
+**Only allow merge requests to be merged if all discussions are resolved** check
+box and hit **Save** for the changes to take effect.
+
+![Only allow merge if all the discussions are resolved settings](img/only_allow_merge_if_all_discussions_are_resolved.png)
+
+From now on, you will not be able to merge from the UI until all discussions
+are resolved.
+
+![Only allow merge if all the discussions are resolved message](img/only_allow_merge_if_all_discussions_are_resolved_msg.png)
+
+## Threaded discussions
+
+> [Introduced][ce-7527] in GitLab 9.1.
+
+While resolvable discussions are only available to merge request diffs,
+discussions can also be added without a diff. You can start a specific
+discussion which will look like a thread, on issues, commits, snippets, and
+merge requests.
+
+To start a threaded discussion, click on the **Comment** button toggle dropdown,
+select **Start discussion** and click **Start discussion** when you're ready to
+post the comment.
+
+![Comment type toggle](img/comment_type_toggle.gif)
+
+This will post a comment with a single thread to allow you to discuss specific
+comments in greater detail.
+
+![Discussion comment](img/discussion_comment.png)
+
+[ce-5022]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5022
+[ce-7125]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7125
+[ce-7527]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7527
+[ce-7180]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7180
+[ce-8266]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8266
+[resolve-discussion-button]: img/resolve_discussion_button.png
+[resolve-comment-button]: img/resolve_comment_button.png
+[discussion-view]: img/discussion_view.png
+[discussions-resolved]: img/discussions_resolved.png
+[markdown]: ../markdown.md
+[quick actions]: ../project/quick_actions.md
+[permissions]: ../permissions.md
diff --git a/doc/user/group/subgroups/img/create_new_group.png b/doc/user/group/subgroups/img/create_new_group.png
new file mode 100644
index 00000000000..9d011ec709a
--- /dev/null
+++ b/doc/user/group/subgroups/img/create_new_group.png
Binary files differ
diff --git a/doc/user/group/subgroups/img/create_subgroup_button.png b/doc/user/group/subgroups/img/create_subgroup_button.png
new file mode 100644
index 00000000000..000b54c2855
--- /dev/null
+++ b/doc/user/group/subgroups/img/create_subgroup_button.png
Binary files differ
diff --git a/doc/user/group/subgroups/img/group_members.png b/doc/user/group/subgroups/img/group_members.png
new file mode 100644
index 00000000000..b95fe6263bf
--- /dev/null
+++ b/doc/user/group/subgroups/img/group_members.png
Binary files differ
diff --git a/doc/user/group/subgroups/img/mention_subgroups.png b/doc/user/group/subgroups/img/mention_subgroups.png
new file mode 100644
index 00000000000..8e6bed0111b
--- /dev/null
+++ b/doc/user/group/subgroups/img/mention_subgroups.png
Binary files differ
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
new file mode 100644
index 00000000000..5724dcfab48
--- /dev/null
+++ b/doc/user/group/subgroups/index.md
@@ -0,0 +1,179 @@
+# Subgroups
+
+>**Notes:**
+- [Introduced][ce-2772] in GitLab 9.0.
+- Not available when using MySQL as external database (support removed in
+ GitLab 9.3 [due to performance reasons][issue]).
+
+With subgroups (aka nested groups or hierarchical groups) you can have
+up to 20 levels of nested groups, which among other things can help you to:
+
+- **Separate internal / external organizations.** Since every group
+ can have its own visibility level, you are able to host groups for different
+ purposes under the same umbrella.
+- **Organize large projects.** For large projects, subgroups makes it
+ potentially easier to separate permissions on parts of the source code.
+- **Make it easier to manage people and control visibility.** Give people
+ different [permissions][] depending on their group [membership](#membership).
+
+## Database Requirements
+
+Nested groups are only supported when you use PostgreSQL. Supporting nested
+groups on MySQL in an efficient way is not possible due to MySQL's limitations.
+See the following links for more information:
+
+* <https://gitlab.com/gitlab-org/gitlab-ce/issues/30472>
+* <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10885>
+
+## Overview
+
+A group can have many subgroups inside it, and at the same time a group can have
+only 1 parent group. It resembles a directory behavior or a nested items list:
+
+- Group 1
+ - Group 1.1
+ - Group 1.2
+ - Group 1.2.1
+ - Group 1.2.2
+ - Group 1.2.2.1
+
+In a real world example, imagine maintaining a GNU/Linux distribution with the
+first group being the name of the distro and subsequent groups split like:
+
+- Organization Group - GNU/Linux distro
+ - Category Subgroup - Packages
+ - (project) Package01
+ - (project) Package02
+ - Category Subgroup - Software
+ - (project) Core
+ - (project) CLI
+ - (project) Android app
+ - (project) iOS app
+ - Category Subgroup - Infra tools
+ - (project) Ansible playbooks
+
+Another example of GitLab as a company would be the following:
+
+- Organization Group - GitLab
+ - Category Subroup - Marketing
+ - (project) Design
+ - (project) General
+ - Category Subgroup - Software
+ - (project) GitLab CE
+ - (project) GitLab EE
+ - (project) Omnibus GitLab
+ - (project) GitLab Runner
+ - (project) GitLab Pages daemon
+ - Category Subgroup - Infra tools
+ - (project) Chef cookbooks
+ - Category Subgroup - Executive team
+
+---
+
+The maximum nested groups a group can have, including the first one in the
+hierarchy, is 21.
+
+Things like transferring or importing a project inside nested groups, work like
+when performing these actions the traditional way with the `group/project`
+structure.
+
+## Creating a subgroup
+
+>**Notes:**
+- You need to be an Owner of a group in order to be able to create
+ a subgroup. For more information check the [permissions table][permissions].
+- For a list of words that are not allowed to be used as group names see the
+ [`path_regex.rb` file][reserved] under the `TOP_LEVEL_ROUTES`, `PROJECT_WILDCARD_ROUTES` and `GROUP_ROUTES` lists:
+ - `TOP_LEVEL_ROUTES`: are names that are reserved as usernames or top level groups
+ - `PROJECT_WILDCARD_ROUTES`: are names that are reserved for child groups or projects.
+ - `GROUP_ROUTES`: are names that are reserved for all groups or projects.
+
+To create a subgroup:
+
+1. In the group's dashboard go to the **Subgroups** page and click **Create subgroup**.
+
+ ![Subgroups page](img/create_subgroup_button.png)
+
+1. Create a new group like you would normally do. Notice that the parent group
+ namespace is fixed under **Group path**. The visibility level can differ from
+ the parent group.
+
+ ![Subgroups page](img/create_new_group.png)
+
+1. Click the **Create group** button and you will be taken to the new group's
+ dashboard page.
+
+---
+
+You can follow the same process to create any subsequent groups.
+
+## Membership
+
+When you add a member to a subgroup, they inherit the membership and permission
+level from the parent group. This model allows access to nested groups if you
+have membership in one of its parents.
+
+The group permissions for a member can be changed only by Owners and only on
+the **Members** page of the group the member was added.
+
+You can tell if a member has inherited the permissions from a parent group by
+looking at the group's **Members** page.
+
+![Group members page](img/group_members.png)
+
+From the image above, we can deduct the following things:
+
+- There are 5 members that have access to the group `four`
+- User0 is a Reporter and has inherited their permissions from group `one`
+ which is above the hierarchy of group `four`
+- User1 is a Developer and has inherited their permissions from group
+ `one/two` which is above the hierarchy of group `four`
+- User2 is a Developer and has inherited their permissions from group
+ `one/two/three` which is above the hierarchy of group `four`
+- For User3 there is no indication of a parent group, therefore they belong to
+ group `four`, the one we're inspecting
+- Administrator is the Owner and member of **all** subgroups and for that reason,
+ same as User3, there is no indication of an ancestor group
+
+### Overriding the ancestor group membership
+
+>**Note:**
+You need to be an Owner of a group in order to be able to add members to it.
+
+To override a user's membership of an ancestor group (the first group they were
+added to), simply add the user in the new subgroup again, but with different
+permissions.
+
+For example, if User0 was first added to group `group-1/group-1-1` with Developer
+permissions, then they will inherit those permissions in every other subgroup
+of `group-1/group-1-1`. To give them Master access to `group-1/group-1-1/group1-1-1`,
+you would add them again in that group as Master. Removing them from that group,
+the permissions will fallback to those of the ancestor group.
+
+## Mentioning subgroups
+
+Mentioning groups (`@group`) in issues, commits and merge requests, would
+notify all members of that group. Now with subgroups, there is a more granular
+support if you want to split your group's structure. Mentioning works as before
+and you can choose the group of people to be notified.
+
+![Mentioning subgroups](img/mention_subgroups.png)
+
+## Limitations
+
+Here's a list of what you can't do with subgroups:
+
+- [GitLab Pages](../../project/pages/index.md) are not currently working for
+ projects hosted under a subgroup. That means that only projects hosted under
+ the first parent group will work.
+- Group level labels don't work in subgroups / sub projects
+- It is not possible to share a project with a group that's an ancestor of
+ the group the project is in. That means you can only share as you walk down
+ the hierarchy. For example, `group/subgroup01/project` **cannot** be shared
+ with `group`, but can be shared with `group/subgroup02` or
+ `group/subgroup01/subgroup03`.
+
+[ce-2772]: https://gitlab.com/gitlab-org/gitlab-ce/issues/2772
+[permissions]: ../../permissions.md#group
+[reserved]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/path_regex.rb
+[issue]: https://gitlab.com/gitlab-org/gitlab-ce/issues/30472#note_27747600
diff --git a/doc/user/img/award_emoji_comment_awarded.png b/doc/user/img/award_emoji_comment_awarded.png
new file mode 100644
index 00000000000..111793ebf8a
--- /dev/null
+++ b/doc/user/img/award_emoji_comment_awarded.png
Binary files differ
diff --git a/doc/user/img/award_emoji_comment_picker.png b/doc/user/img/award_emoji_comment_picker.png
new file mode 100644
index 00000000000..3ad1bab3119
--- /dev/null
+++ b/doc/user/img/award_emoji_comment_picker.png
Binary files differ
diff --git a/doc/user/img/award_emoji_select.png b/doc/user/img/award_emoji_select.png
new file mode 100644
index 00000000000..496acb29eec
--- /dev/null
+++ b/doc/user/img/award_emoji_select.png
Binary files differ
diff --git a/doc/user/img/award_emoji_votes_sort_options.png b/doc/user/img/award_emoji_votes_sort_options.png
new file mode 100644
index 00000000000..dd84b7f4f64
--- /dev/null
+++ b/doc/user/img/award_emoji_votes_sort_options.png
Binary files differ
diff --git a/doc/user/img/gitlab_snippet.png b/doc/user/img/gitlab_snippet.png
new file mode 100644
index 00000000000..718347fc2d4
--- /dev/null
+++ b/doc/user/img/gitlab_snippet.png
Binary files differ
diff --git a/doc/user/img/markdown_logo.png b/doc/user/img/markdown_logo.png
index 05c8b0d0ccf..bb3faaaec76 100644
--- a/doc/user/img/markdown_logo.png
+++ b/doc/user/img/markdown_logo.png
Binary files differ
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index 56e5b802a52..0d29b471d52 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -1,43 +1,5 @@
# Markdown
-## Table of Contents
-
-**[GitLab Flavored Markdown](#gitlab-flavored-markdown-gfm)**
-
-* [Newlines](#newlines)
-* [Multiple underscores in words](#multiple-underscores-in-words)
-* [URL auto-linking](#url-auto-linking)
-* [Multiline Blockquote](#multiline-blockquote)
-* [Code and Syntax Highlighting](#code-and-syntax-highlighting)
-* [Inline Diff](#inline-diff)
-* [Emoji](#emoji)
-* [Special GitLab references](#special-gitlab-references)
-* [Task Lists](#task-lists)
-* [Videos](#videos)
-
-**[Standard Markdown](#standard-markdown)**
-
-* [Headers](#headers)
-* [Emphasis](#emphasis)
-* [Lists](#lists)
-* [Links](#links)
-* [Images](#images)
-* [Blockquotes](#blockquotes)
-* [Inline HTML](#inline-html)
-* [Horizontal Rule](#horizontal-rule)
-* [Line Breaks](#line-breaks)
-* [Tables](#tables)
-* [Footnotes](#footnotes)
-
-**[Wiki-Specific Markdown](#wiki-specific-markdown)**
-
-* [Wiki - Direct page link](#wiki-direct-page-link)
-* [Wiki - Direct file link](#wiki-direct-file-link)
-* [Wiki - Hierarchical link](#wiki-hierarchical-link)
-* [Wiki - Root link](#wiki-root-link)
-
-**[References](#references)**
-
## GitLab Flavored Markdown (GFM)
> **Note:**
@@ -64,7 +26,7 @@ You can use GFM in the following areas:
You can also use other rich text files in GitLab. You might have to install a
dependency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information.
-## Newlines
+### Newlines
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#newlines
@@ -84,7 +46,7 @@ Violets are blue
Sugar is sweet
-## Multiple underscores in words
+### Multiple underscores in words
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#multiple-underscores-in-words
@@ -99,7 +61,7 @@ perform_complicated_task
do_this_and_do_that_and_another_thing
-## URL auto-linking
+### URL auto-linking
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#url-auto-linking
@@ -120,7 +82,7 @@ GFM will autolink almost any URL you copy and paste into your text:
* irc://irc.freenode.net/gitlab
* http://localhost:3000
-## Multiline Blockquote
+### Multiline Blockquote
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#multiline-blockquote
@@ -154,7 +116,7 @@ multiple lines,
you can quote that without having to manually prepend `>` to every line!
>>>
-## Code and Syntax Highlighting
+### Code and Syntax Highlighting
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#code-and-syntax-highlighting
@@ -224,7 +186,7 @@ s = "There is no highlighting for this."
But let's throw in a <b>tag</b>.
```
-## Inline Diff
+### Inline Diff
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#inline-diff
@@ -240,7 +202,7 @@ However the wrapping tags cannot be mixed as such:
- {- deletions -]
- [- deletions -}
-## Emoji
+### Emoji
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#emoji
@@ -265,7 +227,7 @@ If you are new to this, don't be :fearful:. You can easily join the emoji :famil
Consult the [Emoji Cheat Sheet](http://emoji.codes) for a list of all supported emoji codes. :thumbsup:
-## Special GitLab References
+### Special GitLab References
GFM recognizes special references.
@@ -275,23 +237,24 @@ GFM will turn that reference into a link so you can navigate between them easily
GFM will recognize the following:
-| input | references |
-|:-----------------------|:--------------------------- |
-| `@user_name` | specific user |
-| `@group_name` | specific group |
-| `@all` | entire team |
-| `#123` | issue |
-| `!123` | merge request |
-| `$123` | snippet |
-| `~123` | label by ID |
-| `~bug` | one-word label by name |
-| `~"feature request"` | multi-word label by name |
-| `%123` | milestone by ID |
-| `%v1.23` | one-word milestone by name |
-| `%"release candidate"` | multi-word milestone by name |
-| `9ba12248` | specific commit |
-| `9ba12248...b19a04f5` | commit range comparison |
-| `[README](doc/README)` | repository file references |
+| input | references |
+|:---------------------------|:--------------------------------|
+| `@user_name` | specific user |
+| `@group_name` | specific group |
+| `@all` | entire team |
+| `#123` | issue |
+| `!123` | merge request |
+| `$123` | snippet |
+| `~123` | label by ID |
+| `~bug` | one-word label by name |
+| `~"feature request"` | multi-word label by name |
+| `%123` | milestone by ID |
+| `%v1.23` | one-word milestone by name |
+| `%"release candidate"` | multi-word milestone by name |
+| `9ba12248` | specific commit |
+| `9ba12248...b19a04f5` | commit range comparison |
+| `[README](doc/README)` | repository file references |
+| `[README](doc/README#L13)` | repository file line references |
GFM also recognizes certain cross-project references:
@@ -305,7 +268,19 @@ GFM also recognizes certain cross-project references:
| `namespace/project@9ba12248...b19a04f5` | commit range comparison |
| `namespace/project~"Some label"` | issues with given label |
-## Task Lists
+It also has a shorthand version to reference other projects from the same namespace:
+
+| input | references |
+|:------------------------------|:------------------------|
+| `project#123` | issue |
+| `project!123` | merge request |
+| `project%123` | milestone |
+| `project$123` | snippet |
+| `project@9ba12248` | specific commit |
+| `project@9ba12248...b19a04f5` | commit range comparison |
+| `project~"Some label"` | issues with given label |
+
+### Task Lists
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#task-lists
@@ -326,9 +301,23 @@ You can add task lists to issues, merge requests and comments. To create a task
- [x] Sub-task 2
- [ ] Sub-task 3
+Tasks formatted as ordered lists are supported as well:
+
+```no-highlight
+1. [x] Completed task
+1. [ ] Incomplete task
+ 1. [ ] Sub-task 1
+ 1. [x] Sub-task 2
+```
+
+1. [x] Completed task
+1. [ ] Incomplete task
+ 1. [ ] Sub-task 1
+ 1. [x] Sub-task 2
+
Task lists can only be created in descriptions, not in titles. Task item state can be managed by editing the description's Markdown or by toggling the rendered check boxes.
-## Videos
+### Videos
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#videos
@@ -345,27 +334,45 @@ Here's a sample video:
![Sample Video](img/markdown_video.mp4)
-# Standard Markdown
+### Math
-## Headers
+> If this is not rendered correctly, see
+https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#math
-```no-highlight
-# H1
-## H2
-### H3
-#### H4
-##### H5
-###### H6
+It is possible to have math written with the LaTeX syntax rendered using [KaTeX][katex].
-Alternatively, for H1 and H2, an underline-ish style:
+Math written inside ```$``$``` will be rendered inline with the text.
-Alt-H1
-======
+Math written inside triple back quotes, with the language declared as `math`, will be rendered on a separate line.
-Alt-H2
-------
+Example:
+
+ This math is inline $`a^2+b^2=c^2`$.
+
+ This is on a separate line
+ ```math
+ a^2+b^2=c^2
+ ```
+
+Becomes:
+
+This math is inline $`a^2+b^2=c^2`$.
+
+This is on a separate line
+```math
+a^2+b^2=c^2
```
+_Be advised that KaTeX only supports a [subset][katex-subset] of LaTeX._
+
+>**Note:**
+This also works for the asciidoctor `:stem: latexmath`. For details see the [asciidoctor user manual][asciidoctor-manual].
+
+## Standard Markdown
+
+### Headers
+
+```no-highlight
# H1
## H2
### H3
@@ -380,6 +387,7 @@ Alt-H1
Alt-H2
------
+```
### Header IDs and links
@@ -416,7 +424,7 @@ Would generate the following link IDs:
Note that the Emoji processing happens before the header IDs are generated, so the Emoji is converted to an image which then gets removed from the ID.
-## Emphasis
+### Emphasis
```no-highlight
Emphasis, aka italics, with *asterisks* or _underscores_.
@@ -436,7 +444,7 @@ Combined emphasis with **asterisks and _underscores_**.
Strikethrough uses two tildes. ~~Scratch this.~~
-## Lists
+### Lists
```no-highlight
1. First ordered list item
@@ -492,7 +500,7 @@ the second list item will be incorrectly labeled as `1`.
Second paragraph of first item.
2. Another item
-## Links
+### Links
There are two ways to create links, inline-style and reference-style.
@@ -502,6 +510,10 @@ There are two ways to create links, inline-style and reference-style.
[I'm a relative reference to a repository file](LICENSE)
+ [I am an absolute reference within the repository](/doc/user/markdown.md)
+
+ [I link to the Milestones page](/../milestones)
+
[You can use numbers for reference-style link definitions][1]
Or leave it empty and use the [link text itself][]
@@ -512,31 +524,13 @@ There are two ways to create links, inline-style and reference-style.
[1]: http://slashdot.org
[link text itself]: https://www.reddit.com
-[I'm an inline-style link](https://www.google.com)
-
-[I'm a reference-style link][Arbitrary case-insensitive reference text]
-
-[I'm a relative reference to a repository file](LICENSE)[^1]
-
-[You can use numbers for reference-style link definitions][1]
-
-Or leave it empty and use the [link text itself][]
-
-Some text to show that the reference links can follow later.
-
-[arbitrary case-insensitive reference text]: https://www.mozilla.org
-[1]: http://slashdot.org
-[link text itself]: https://www.reddit.com
-
-**Note**
-
-Relative links do not allow referencing project files in a wiki page or wiki page in a project file. The reason for this is that, in GitLab, wiki is always a separate git repository. For example:
-
-`[I'm a reference-style link](style)`
-
+>**Note:**
+Relative links do not allow referencing project files in a wiki page or wiki
+page in a project file. The reason for this is that, in GitLab, wiki is always
+a separate Git repository. For example, `[I'm a reference-style link](style)`
will point the link to `wikis/style` when the link is inside of a wiki markdown file.
-## Images
+### Images
Here's our logo (hover to see the title text):
@@ -560,7 +554,7 @@ Reference-style:
[logo]: img/markdown_logo.png
-## Blockquotes
+### Blockquotes
```no-highlight
> Blockquotes are very handy in email to emulate reply text.
@@ -578,11 +572,11 @@ Quote break.
> This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **Markdown** into a blockquote.
-## Inline HTML
+### Inline HTML
You can also use raw HTML in your Markdown, and it'll mostly work pretty well.
-See the documentation for HTML::Pipeline's [SanitizationFilter](http://www.rubydoc.info/gems/html-pipeline/HTML/Pipeline/SanitizationFilter#WHITELIST-constant) class for the list of allowed HTML tags and attributes. In addition to the default `SanitizationFilter` whitelist, GitLab allows `span` elements.
+See the documentation for HTML::Pipeline's [SanitizationFilter](http://www.rubydoc.info/gems/html-pipeline/1.11.0/HTML/Pipeline/SanitizationFilter#WHITELIST-constant) class for the list of allowed HTML tags and attributes. In addition to the default `SanitizationFilter` whitelist, GitLab allows `span`, `abbr`, `details` and `summary` elements.
```no-highlight
<dl>
@@ -602,7 +596,7 @@ See the documentation for HTML::Pipeline's [SanitizationFilter](http://www.rubyd
<dd>Does *not* work **very** well. Use HTML <em>tags</em>.</dd>
</dl>
-## Horizontal Rule
+### Horizontal Rule
```
Three or more...
@@ -634,7 +628,7 @@ ___
Underscores
-## Line Breaks
+### Line Breaks
My basic recommendation for learning how line breaks work is to experiment and discover -- hit &lt;Enter&gt; once (i.e., insert one newline), then hit it twice (i.e., insert two newlines), see what happens. You'll soon learn to get what you want. "Markdown Toggle" is your friend.
@@ -646,10 +640,11 @@ Here's a line for us to start with.
This line is separated from the one above by two newlines, so it will be a *separate paragraph*.
This line is also a separate paragraph, but...
-This line is only separated by a single newline, so it's a separate line in the *same paragraph*.
+This line is only separated by a single newline, so it *does not break* and just follows the previous line in the *same paragraph*.
+
+This line is also a separate paragraph, and...
+This line is *on its own line*, because the previous line ends with two spaces. (but still in the *same paragraph*)
-This line is also a separate paragraph, and...
-This line is on its own line, because the previous line ends with two
spaces.
```
@@ -657,14 +652,15 @@ Here's a line for us to start with.
This line is separated from the one above by two newlines, so it will be a *separate paragraph*.
-This line is also begins a separate paragraph, but...
-This line is only separated by a single newline, so it's a separate line in the *same paragraph*.
+This line is also a separate paragraph, but...
+This line is only separated by a single newline, so it *does not break* and just follows the previous line in the *same paragraph*.
+
+This line is also a separate paragraph, and...
+This line is *on its own line*, because the previous line ends with two spaces. (but still in the *same paragraph*)
-This line is also a separate paragraph, and...
-This line is on its own line, because the previous line ends with two
spaces.
-## Tables
+### Tables
Tables aren't part of the core Markdown spec, but they are part of GFM and Markdown Here supports them.
@@ -700,16 +696,15 @@ By including colons in the header row, you can align the text within that column
| Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 |
| Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 |
-## Footnotes
-
-You can add footnotes to your text as follows.[^1]
-[^1]: This is my awesome footnote.
+### Footnotes
```
-You can add footnotes to your text as follows.[^1]
-[^1]: This is my awesome footnote.
+You can add footnotes to your text as follows.[^2]
+[^2]: This is my awesome footnote.
```
+You can add footnotes to your text as follows.[^2]
+
## Wiki-specific Markdown
The following examples show how links inside wikis behave.
@@ -744,30 +739,30 @@ A link can be constructed relative to the current wiki page using `./<page>`,
- If this snippet was placed on a page at `<your_wiki>/documentation/main`,
it would link to `<your_wiki>/documentation/related`:
- ```markdown
- [Link to Related Page](./related)
- ```
+ ```markdown
+ [Link to Related Page](./related)
+ ```
- If this snippet was placed on a page at `<your_wiki>/documentation/related/content`,
it would link to `<your_wiki>/documentation/main`:
- ```markdown
- [Link to Related Page](../main)
- ```
+ ```markdown
+ [Link to Related Page](../main)
+ ```
- If this snippet was placed on a page at `<your_wiki>/documentation/main`,
it would link to `<your_wiki>/documentation/related.md`:
- ```markdown
- [Link to Related Page](./related.md)
- ```
+ ```markdown
+ [Link to Related Page](./related.md)
+ ```
- If this snippet was placed on a page at `<your_wiki>/documentation/related/content`,
it would link to `<your_wiki>/documentation/main.md`:
- ```markdown
- [Link to Related Page](../main.md)
- ```
+ ```markdown
+ [Link to Related Page](../main.md)
+ ```
### Wiki - Root link
@@ -775,22 +770,28 @@ A link starting with a `/` is relative to the wiki root.
- This snippet links to `<wiki_root>/documentation`:
- ```markdown
- [Link to Related Page](/documentation)
- ```
+ ```markdown
+ [Link to Related Page](/documentation)
+ ```
- This snippet links to `<wiki_root>/miscellaneous.md`:
- ```markdown
- [Link to Related Page](/miscellaneous.md)
- ```
+ ```markdown
+ [Link to Related Page](/miscellaneous.md)
+ ```
+
## References
- This document leveraged heavily from the [Markdown-Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet).
- The [Markdown Syntax Guide](https://daringfireball.net/projects/markdown/syntax) at Daring Fireball is an excellent resource for a detailed explanation of standard markdown.
- [Dillinger.io](http://dillinger.io) is a handy tool for testing standard markdown.
+[^1]: This link will be broken if you see this document from the Help page or docs.gitlab.com
+[^2]: This is my awesome footnote.
+
[markdown.md]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md
[rouge]: http://rouge.jneen.net/ "Rouge website"
[redcarpet]: https://github.com/vmg/redcarpet "Redcarpet website"
-[^1]: This link will be broken if you see this document from the Help page or docs.gitlab.com
+[katex]: https://github.com/Khan/KaTeX "KaTeX website"
+[katex-subset]: https://github.com/Khan/KaTeX/wiki/Function-Support-in-KaTeX "Macros supported by KaTeX"
+[asciidoctor-manual]: http://asciidoctor.org/docs/user-manual/#activating-stem-support "Asciidoctor user manual"
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index c0dc80325b6..3d47e644ad2 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -7,6 +7,9 @@ project itself, the highest permission level is used.
On public and internal projects the Guest role is not enforced. All users will
be able to create issues, leave comments, and pull or download the project code.
+When a member leaves the team the all assigned Issues and Merge Requests
+will be unassigned automatically.
+
GitLab administrators receive all permissions.
To add or import a user, you can follow the [project users and members
@@ -19,10 +22,12 @@ The following table depicts the various user permission levels in a project.
| Action | Guest | Reporter | Developer | Master | Owner |
|---------------------------------------|---------|------------|-------------|----------|--------|
| Create new issue | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Create confidential issue | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View confidential issues | (✓) [^1] | ✓ | ✓ | ✓ | ✓ |
| Leave comments | ✓ | ✓ | ✓ | ✓ | ✓ |
-| See a list of builds | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
-| See a build log | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
-| Download and browse build artifacts | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
+| See a list of jobs | ✓ [^2] | ✓ | ✓ | ✓ | ✓ |
+| See a job log | ✓ [^2] | ✓ | ✓ | ✓ | ✓ |
+| Download and browse job artifacts | ✓ [^2] | ✓ | ✓ | ✓ | ✓ |
| View wiki pages | ✓ | ✓ | ✓ | ✓ | ✓ |
| Pull project code | | ✓ | ✓ | ✓ | ✓ |
| Download project | | ✓ | ✓ | ✓ | ✓ |
@@ -32,6 +37,10 @@ The following table depicts the various user permission levels in a project.
| See a commit status | | ✓ | ✓ | ✓ | ✓ |
| See a container registry | | ✓ | ✓ | ✓ | ✓ |
| See environments | | ✓ | ✓ | ✓ | ✓ |
+| Create new environments | | | ✓ | ✓ | ✓ |
+| Use environment terminals | | | | ✓ | ✓ |
+| Stop environments | | | ✓ | ✓ | ✓ |
+| See a list of merge requests | | ✓ | ✓ | ✓ | ✓ |
| Manage/Accept merge requests | | | ✓ | ✓ | ✓ |
| Create new merge request | | | ✓ | ✓ | ✓ |
| Create new branches | | | ✓ | ✓ | ✓ |
@@ -40,32 +49,31 @@ The following table depicts the various user permission levels in a project.
| Remove non-protected branches | | | ✓ | ✓ | ✓ |
| Add tags | | | ✓ | ✓ | ✓ |
| Write a wiki | | | ✓ | ✓ | ✓ |
-| Cancel and retry builds | | | ✓ | ✓ | ✓ |
+| Cancel and retry jobs | | | ✓ | ✓ | ✓ |
| Create or update commit status | | | ✓ | ✓ | ✓ |
| Update a container registry | | | ✓ | ✓ | ✓ |
| Remove a container registry image | | | ✓ | ✓ | ✓ |
-| Create new environments | | | ✓ | ✓ | ✓ |
| Create new milestones | | | | ✓ | ✓ |
| Add new team members | | | | ✓ | ✓ |
| Push to protected branches | | | | ✓ | ✓ |
| Enable/disable branch protection | | | | ✓ | ✓ |
| Turn on/off protected branch push for devs| | | | ✓ | ✓ |
+| Enable/disable tag protections | | | | ✓ | ✓ |
| Rewrite/remove Git tags | | | | ✓ | ✓ |
| Edit project | | | | ✓ | ✓ |
| Add deploy keys to project | | | | ✓ | ✓ |
| Configure project hooks | | | | ✓ | ✓ |
| Manage runners | | | | ✓ | ✓ |
-| Manage build triggers | | | | ✓ | ✓ |
+| Manage job triggers | | | | ✓ | ✓ |
| Manage variables | | | | ✓ | ✓ |
-| Delete environments | | | | ✓ | ✓ |
+| Manage pages | | | | ✓ | ✓ |
+| Manage pages domains and certificates | | | | ✓ | ✓ |
| Switch visibility level | | | | | ✓ |
| Transfer project to another namespace | | | | | ✓ |
| Remove project | | | | | ✓ |
-| Force push to protected branches [^2] | | | | | |
-| Remove protected branches [^2] | | | | | |
-
-[^1]: If **Public pipelines** is enabled in **Project Settings > CI/CD Pipelines**
-[^2]: Not allowed for Guest, Reporter, Developer, Master, or Owner
+| Force push to protected branches [^3] | | | | | |
+| Remove protected branches [^3] | | | | | |
+| Remove pages | | | | | ✓ |
## Group
@@ -77,9 +85,11 @@ group.
|-------------------------|-------|----------|-----------|--------|-------|
| Browse group | ✓ | ✓ | ✓ | ✓ | ✓ |
| Edit group | | | | | ✓ |
+| Create subgroup | | | | | ✓ |
| Create project in group | | | | ✓ | ✓ |
| Manage group members | | | | | ✓ |
| Remove group | | | | | ✓ |
+| Manage group labels | | ✓ | ✓ | ✓ | ✓ |
## External Users
@@ -117,7 +127,7 @@ which visibility level you select on project settings.
## GitLab CI
GitLab CI permissions rely on the role the user has in GitLab. There are four
-permission levels it total:
+permission levels in total:
- admin
- master
@@ -130,8 +140,8 @@ instance and project. In addition, all admins can use the admin interface under
| Action | Guest, Reporter | Developer | Master | Admin |
|---------------------------------------|-----------------|-------------|----------|--------|
-| See commits and builds | ✓ | ✓ | ✓ | ✓ |
-| Retry or cancel build | | ✓ | ✓ | ✓ |
+| See commits and jobs | ✓ | ✓ | ✓ | ✓ |
+| Retry or cancel job | | ✓ | ✓ | ✓ |
| Remove project | | | ✓ | ✓ |
| Create project | | | ✓ | ✓ |
| Change project configuration | | | ✓ | ✓ |
@@ -140,32 +150,34 @@ instance and project. In addition, all admins can use the admin interface under
| See events in the system | | | | ✓ |
| Admin interface | | | | ✓ |
-### Build permissions
-
-> Changed in GitLab 8.12.
+### Jobs permissions
-GitLab 8.12 has a completely redesigned build permissions system.
+>**Note:**
+GitLab 8.12 has a completely redesigned job permissions system.
Read all about the [new model and its implications][new-mod].
-This table shows granted privileges for builds triggered by specific types of
+This table shows granted privileges for jobs triggered by specific types of
users:
| Action | Guest, Reporter | Developer | Master | Admin |
|---------------------------------------------|-----------------|-------------|----------|--------|
-| Run CI build | | ✓ | ✓ | ✓ |
+| Run CI job | | ✓ | ✓ | ✓ |
| Clone source and LFS from current project | | ✓ | ✓ | ✓ |
| Clone source and LFS from public projects | | ✓ | ✓ | ✓ |
-| Clone source and LFS from internal projects | | ✓ [^3] | ✓ [^3] | ✓ |
-| Clone source and LFS from private projects | | ✓ [^4] | ✓ [^4] | ✓ [^4] |
+| Clone source and LFS from internal projects | | ✓ [^4] | ✓ [^4] | ✓ |
+| Clone source and LFS from private projects | | ✓ [^5] | ✓ [^5] | ✓ [^5] |
| Push source and LFS | | | | |
| Pull container images from current project | | ✓ | ✓ | ✓ |
| Pull container images from public projects | | ✓ | ✓ | ✓ |
-| Pull container images from internal projects| | ✓ [^3] | ✓ [^3] | ✓ |
-| Pull container images from private projects | | ✓ [^4] | ✓ [^4] | ✓ [^4] |
+| Pull container images from internal projects| | ✓ [^4] | ✓ [^4] | ✓ |
+| Pull container images from private projects | | ✓ [^5] | ✓ [^5] | ✓ [^5] |
| Push container images to current project | | ✓ | ✓ | ✓ |
| Push container images to other projects | | | | |
-[^3]: Only if user is not external one.
-[^4]: Only if user is a member of the project.
+[^1]: Guest users can only view the confidential issues they created themselves
+[^2]: If **Public pipelines** is enabled in **Project Settings > Pipelines**
+[^3]: Not allowed for Guest, Reporter, Developer, Master, or Owner
+[^4]: Only if user is not external one.
+[^5]: Only if user is a member of the project.
[ce-18994]: https://gitlab.com/gitlab-org/gitlab-ce/issues/18994
[new-mod]: project/new_ci_build_permissions_model.md
diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md
new file mode 100644
index 00000000000..e7596f5c577
--- /dev/null
+++ b/doc/user/profile/account/delete_account.md
@@ -0,0 +1,35 @@
+# Deleting a User Account
+
+- As a user, you can delete your own account by navigating to **Settings** > **Account** and selecting **Delete account**
+- As an admin, you can delete a user account by navigating to the **Admin Area**, selecting the **Users** tab, selecting a user, and clicking on **Remove user**
+
+## Associated Records
+
+> Introduced for issues in [GitLab 9.0][ce-7393], and for merge requests, award
+ emoji, notes, and abuse reports in [GitLab 9.1][ce-10467].
+ Hard deletion from abuse reports and spam logs was introduced in
+ [GitLab 9.1][ce-10273], and from the API in [GitLab 9.3][ce-11853].
+
+When a user account is deleted, not all associated records are deleted with it.
+Here's a list of things that will not be deleted:
+
+- Issues that the user created
+- Merge requests that the user created
+- Notes that the user created
+- Abuse reports that the user reported
+- Award emoji that the user created
+
+Instead of being deleted, these records will be moved to a system-wide
+"Ghost User", whose sole purpose is to act as a container for such records.
+
+When a user is deleted from an abuse report or spam log, these associated
+records are not ghosted and will be removed, along with any groups the user
+is a sole owner of. Administrators can also request this behaviour when
+deleting users from the [API](../../../api/users.md#user-deletion) or the
+admin area.
+
+[ce-7393]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7393
+[ce-10273]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10273
+[ce-10467]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10467
+[ce-11853]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11853
+
diff --git a/doc/profile/2fa.png b/doc/user/profile/account/img/2fa.png
index bb464efa685..bb464efa685 100644
--- a/doc/profile/2fa.png
+++ b/doc/user/profile/account/img/2fa.png
Binary files differ
diff --git a/doc/profile/2fa_auth.png b/doc/user/profile/account/img/2fa_auth.png
index 0caaed10805..0caaed10805 100644
--- a/doc/profile/2fa_auth.png
+++ b/doc/user/profile/account/img/2fa_auth.png
Binary files differ
diff --git a/doc/user/profile/account/img/2fa_u2f_authenticate.png b/doc/user/profile/account/img/2fa_u2f_authenticate.png
new file mode 100644
index 00000000000..ff2e936764d
--- /dev/null
+++ b/doc/user/profile/account/img/2fa_u2f_authenticate.png
Binary files differ
diff --git a/doc/user/profile/account/img/2fa_u2f_register.png b/doc/user/profile/account/img/2fa_u2f_register.png
new file mode 100644
index 00000000000..1cc142aa851
--- /dev/null
+++ b/doc/user/profile/account/img/2fa_u2f_register.png
Binary files differ
diff --git a/doc/user/profile/account/index.md b/doc/user/profile/account/index.md
new file mode 100644
index 00000000000..764354e1e96
--- /dev/null
+++ b/doc/user/profile/account/index.md
@@ -0,0 +1,5 @@
+# Profile settings
+
+## Account
+
+Set up [two-factor authentication](two_factor_authentication.md).
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
new file mode 100644
index 00000000000..590c3f862fb
--- /dev/null
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -0,0 +1,223 @@
+# Two-Factor Authentication
+
+Two-factor Authentication (2FA) provides an additional level of security to your
+GitLab account. Once enabled, in addition to supplying your username and
+password to login, you'll be prompted for a code generated by an application on
+your phone.
+
+By enabling 2FA, the only way someone other than you can log into your account
+is to know your username and password *and* have access to your phone.
+
+## Overview
+
+> **Note:**
+When you enable 2FA, don't forget to back up your recovery codes.
+
+In addition to a phone application, GitLab supports U2F (universal 2nd factor) devices as
+the second factor of authentication. Once enabled, in addition to supplying your username and
+password to login, you'll be prompted to activate your U2F device (usually by pressing
+a button on it), and it will perform secure authentication on your behalf.
+
+The U2F workflow is only supported by Google Chrome at this point, so we _strongly_ recommend
+that you set up both methods of two-factor authentication, so you can still access your account
+from other browsers.
+
+## Enabling 2FA
+
+There are two ways to enable two-factor authentication: via a mobile application
+or a U2F device.
+
+### Enable 2FA via mobile application
+
+**In GitLab:**
+
+1. Log in to your GitLab account.
+1. Go to your **Profile Settings**.
+1. Go to **Account**.
+1. Click **Enable Two-factor Authentication**.
+
+![Two-factor setup](img/2fa.png)
+
+**On your phone:**
+
+1. Install a compatible application. We recommend [Google Authenticator]
+\(proprietary\) or [FreeOTP] \(open source\).
+1. In the application, add a new entry in one of two ways:
+ * Scan the code with your phone's camera to add the entry automatically.
+ * Enter the details provided to add the entry manually.
+
+**In GitLab:**
+
+1. Enter the six-digit pin number from the entry on your phone into the **Pin
+ code** field.
+1. Click **Submit**.
+
+If the pin you entered was correct, you'll see a message indicating that
+Two-Factor Authentication has been enabled, and you'll be presented with a list
+of recovery codes.
+
+### Enable 2FA via U2F device
+
+> **Notes:**
+- GitLab officially only supports [Yubikey] U2F devices.
+- Support for U2F devices was added in GitLab 8.8.
+
+**In GitLab:**
+
+1. Log in to your GitLab account.
+1. Go to your **Profile Settings**.
+1. Go to **Account**.
+1. Click **Enable Two-Factor Authentication**.
+1. Plug in your U2F device.
+1. Click on **Setup New U2F Device**.
+1. A light will start blinking on your device. Activate it by pressing its button.
+
+You will see a message indicating that your device was successfully set up.
+Click on **Register U2F Device** to complete the process.
+
+![Two-Factor U2F Setup](img/2fa_u2f_register.png)
+
+## Recovery Codes
+
+> **Note:**
+Recovery codes are not generated for U2F devices.
+
+Should you ever lose access to your phone, you can use one of the ten provided
+backup codes to login to your account. We suggest copying or printing them for
+storage in a safe place. **Each code can be used only once** to log in to your
+account.
+
+If you lose the recovery codes or just want to generate new ones, you can do so
+from the **Profile settings ➔ Account** page where you first enabled 2FA.
+
+## Logging in with 2FA Enabled
+
+Logging in with 2FA enabled is only slightly different than a normal login.
+Enter your username and password credentials as you normally would, and you'll
+be presented with a second prompt, depending on which type of 2FA you've enabled.
+
+### Log in via mobile application
+
+Enter the pin from your phone's application or a recovery code to log in.
+
+![Two-Factor Authentication on sign in via OTP](img/2fa_auth.png)
+
+### Log in via U2F device
+
+1. Click **Login via U2F Device**
+1. A light will start blinking on your device. Activate it by pressing its button.
+
+You will see a message indicating that your device responded to the authentication request.
+Click on **Authenticate via U2F Device** to complete the process.
+
+![Two-Factor Authentication on sign in via U2F device](img/2fa_u2f_authenticate.png)
+
+## Disabling 2FA
+
+1. Log in to your GitLab account.
+1. Go to your **Profile Settings**.
+1. Go to **Account**.
+1. Click **Disable**, under **Two-Factor Authentication**.
+
+This will clear all your two-factor authentication registrations, including mobile
+applications and U2F devices.
+
+## Personal access tokens
+
+When 2FA is enabled, you can no longer use your normal account password to
+authenticate with Git over HTTPS on the command line or when using
+[GitLab's API][api], you must use a [personal access token][pat] instead.
+
+## Recovery options
+
+To disable two-factor authentication on your account (for example, if you
+have lost your code generation device) you can:
+
+* [Use a saved recovery code](#use-a-saved-recovery-code)
+* [Generate new recovery codes using SSH](#generate-new-recovery-codes-using-ssh)
+* [Ask a GitLab administrator to disable two-factor authentication on your account](#ask-a-gitlab-administrator-to-disable-two-factor-authentication-on-your-account)
+
+### Use a saved recovery code
+
+Enabling two-factor authentication for your account generated several recovery
+codes. If you saved these codes, you can use one of them to sign in.
+
+To use a recovery code, enter your username/email and password on the GitLab
+sign-in page. When prompted for a two-factor code, enter the recovery code.
+
+>**Note:**
+Once you use a recovery code, you cannot re-use it. You can still use the other
+recovery codes you saved.
+
+### Generate new recovery codes using SSH
+
+Users often forget to save their recovery codes when enabling two-factor
+authentication. If an SSH key is added to your GitLab account, you can generate
+a new set of recovery codes with SSH.
+
+1. Run `ssh git@gitlab.example.com 2fa_recovery_codes`.
+2. You are prompted to confirm that you want to generate new codes. Continuing this process invalidates previously saved codes.
+ ```
+ bash
+ $ ssh git@gitlab.example.com 2fa_recovery_codes
+ Are you sure you want to generate new two-factor recovery codes?
+ Any existing recovery codes you saved will be invalidated. (yes/no)
+
+ yes
+
+ Your two-factor authentication recovery codes are:
+
+ 119135e5a3ebce8e
+ 11f6v2a498810dcd
+ 3924c7ab2089c902
+ e79a3398bfe4f224
+ 34bd7b74adbc8861
+ f061691d5107df1a
+ 169bf32a18e63e7f
+ b510e7422e81c947
+ 20dbed24c5e74663
+ df9d3b9403b9c9f0
+
+ During sign in, use one of the codes above when prompted for your
+ two-factor code. Then, visit your Profile Settings and add a new device
+ so you do not lose access to your account again.
+ ```
+
+3. Go to the GitLab sign-in page and enter your username/email and password.
+ When prompted for a two-factor code, enter one of the recovery codes obtained
+ from the command-line output.
+
+>**Note:**
+After signing in, visit your **Profile settings > Account** immediately to set
+up two-factor authentication with a new device.
+
+### Ask a GitLab administrator to disable two-factor authentication on your account
+
+If you cannot use a saved recovery code or generate new recovery codes, ask a
+GitLab global administrator to disable two-factor authentication for your
+account. This will temporarily leave your account in a less secure state.
+Sign in and re-enable two-factor authentication as soon as possible.
+
+## Note to GitLab administrators
+
+- You need to take special care to that 2FA keeps working after
+ [restoring a GitLab backup](../../../raketasks/backup_restore.md).
+- To ensure 2FA authorizes correctly with TOTP server, you may want to ensure
+ your GitLab server's time is synchronized via a service like NTP. Otherwise,
+ you may have cases where authorization always fails because of time differences.
+- The GitLab U2F implementation does _not_ work when the GitLab instance is accessed from
+ multiple hostnames, or FQDNs. Each U2F registration is linked to the _current hostname_ at
+ the time of registration, and cannot be used for other hostnames/FQDNs.
+
+ For example, if a user is trying to access a GitLab instance from `first.host.xyz` and `second.host.xyz`:
+
+ - The user logs in via `first.host.xyz` and registers their U2F key.
+ - The user logs out and attempts to log in via `first.host.xyz` - U2F authentication suceeds.
+ - The user logs out and attempts to log in via `second.host.xyz` - U2F authentication fails, because
+ the U2F key has only been registered on `first.host.xyz`.
+
+[Google Authenticator]: https://support.google.com/accounts/answer/1066447?hl=en
+[FreeOTP]: https://freeotp.github.io/
+[YubiKey]: https://www.yubico.com/products/yubikey-hardware/
+[api]: ../../../api/README.md
+[pat]: ../personal_access_tokens.md
diff --git a/doc/user/profile/img/personal_access_tokens.png b/doc/user/profile/img/personal_access_tokens.png
new file mode 100644
index 00000000000..6aa63dbe342
--- /dev/null
+++ b/doc/user/profile/img/personal_access_tokens.png
Binary files differ
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
new file mode 100644
index 00000000000..9488ce1ef30
--- /dev/null
+++ b/doc/user/profile/personal_access_tokens.md
@@ -0,0 +1,57 @@
+# Personal access tokens
+
+> [Introduced][ce-3749] in GitLab 8.8.
+
+Personal access tokens are useful if you need access to the [GitLab API][api].
+Instead of using your private token which grants full access to your account,
+personal access tokens could be a better fit because of their
+[granular permissions](#limiting-scopes-of-a-personal-access-token).
+
+You can also use them to authenticate against Git over HTTP. They are the only
+accepted method of authentication when you have
+[Two-Factor Authentication (2FA)][2fa] enabled.
+
+Once you have your token, [pass it to the API][usage] using either the
+`private_token` parameter or the `PRIVATE-TOKEN` header.
+
+## Creating a personal access token
+
+You can create as many personal access tokens as you like from your GitLab
+profile.
+
+1. Log in to your GitLab account.
+1. Go to your **Profile settings**.
+1. Go to **Access tokens**.
+1. Choose a name and optionally an expiry date for the token.
+1. Choose the [desired scopes](#limiting-scopes-of-a-personal-access-token).
+1. Click on **Create personal access token**.
+1. Save the personal access token somewhere safe. Once you leave or refresh
+ the page, you won't be able to access it again.
+
+![Personal access tokens page](img/personal_access_tokens.png)
+
+## Revoking a personal access token
+
+At any time, you can revoke any personal access token by just clicking the
+respective **Revoke** button under the 'Active personal access tokens' area.
+
+## Limiting scopes of a personal access token
+
+Personal access tokens can be created with one or more scopes that allow various
+actions that a given token can perform. The available scopes are depicted in
+the following table.
+
+| Scope | Description |
+| ----- | ----------- |
+|`read_user` | Allows access to the read-only endpoints under `/users`. Essentially, any of the `GET` requests in the [Users API][users] are allowed ([introduced][ce-5951] in GitLab 8.15). |
+| `api` | Grants complete access to the API (read/write) ([introduced][ce-5951] in GitLab 8.15). Required for accessing Git repositories over HTTP when 2FA is enabled. |
+| `read_registry` | Allows to read [container registry] images if a project is private and authorization is required ([introduced][ce-11845] in GitLab 9.3). |
+
+[2fa]: ../account/two_factor_authentication.md
+[api]: ../../api/README.md
+[ce-3749]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3749
+[ce-5951]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5951
+[ce-11845]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845
+[container registry]: ../project/container_registry.md
+[users]: ../../api/users.md
+[usage]: ../../api/README.md#basic-usage
diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md
new file mode 100644
index 00000000000..f2ad42f21fd
--- /dev/null
+++ b/doc/user/profile/preferences.md
@@ -0,0 +1,64 @@
+# Profile preferences
+
+A user's profile preferences page allows the user to customize various aspects
+of GitLab to their liking.
+
+To navigate to your profile's preferences, click your avatar icon in the top
+right corner and select **Settings**. From there on, choose the **Preferences**
+tab.
+
+## Syntax highlighting theme
+
+>**Note:**
+GitLab uses the [rouge Ruby library][rouge] for syntax highlighting. For a
+list of supported languages visit the rouge website.
+
+Changing this setting allows you to customize the color theme when viewing any
+syntax highlighted code on GitLab.
+
+The default one is **White**, and you can choose among 5 different colors:
+
+- White
+- Dark
+- Solarized light
+- Solarized dark
+- Monokai
+
+## Behavior
+
+The following settings allow you to customize the behavior of GitLab's layout
+and default views of your dashboard and the projects' landing pages.
+
+### Layout width
+
+GitLab can be set up to use different widths depending on your liking. Choose
+between the fixed (max. 1200px) and the fluid (100%) application layout.
+
+### Default dashboard
+
+For users who have access to a large number of projects but only keep up with a
+select few, the amount of activity on the default Dashboard page can be
+overwhelming. Changing this setting allows you to redefine what your default
+dashboard will be.
+
+You have 6 options here that you can use for your default dashboard view:
+
+- Your projects (default)
+- Starred projects
+- Your projects' activity
+- Starred projects' activity
+- Your groups
+- Your [Todos]
+
+### Project home page content
+
+The project home page content setting allows you to choose what content you want to
+see on a project’s home page.
+
+You can choose between 2 options:
+
+- Show the files and the readme (default)
+- Show the project’s activity
+
+[rouge]: http://rouge.jneen.net/ "Rouge website"
+[todos]: ../../workflow/todos.md
diff --git a/doc/user/project/builds/artifacts.md b/doc/user/project/builds/artifacts.md
index 88f1863dddb..514c729b37d 100644
--- a/doc/user/project/builds/artifacts.md
+++ b/doc/user/project/builds/artifacts.md
@@ -1,136 +1 @@
-# Introduction to build artifacts
-
->**Notes:**
->- Since GitLab 8.2 and GitLab Runner 0.7.0, build artifacts that are created by
- GitLab Runner are uploaded to GitLab and are downloadable as a single archive
- (`tar.gz`) using the GitLab UI.
->- Starting from GitLab 8.4 and GitLab Runner 1.0, the artifacts archive format
- changed to `ZIP`, and it is now possible to browse its contents, with the added
- ability of downloading the files separately.
->- The artifacts browser will be available only for new artifacts that are sent
- to GitLab using GitLab Runner version 1.0 and up. It will not be possible to
- browse old artifacts already uploaded to GitLab.
->- This is the user documentation. For the administration guide see
- [administration/build_artifacts.md](../../../administration/build_artifacts.md).
-
-Artifacts is a list of files and directories which are attached to a build
-after it completes successfully. This feature is enabled by default in all GitLab installations.
-
-## Defining artifacts in `.gitlab-ci.yml`
-
-A simple example of using the artifacts definition in `.gitlab-ci.yml` would be
-the following:
-
-```yaml
-pdf:
- script: xelatex mycv.tex
- artifacts:
- paths:
- - mycv.pdf
-```
-
-A job named `pdf` calls the `xelatex` command in order to build a pdf file from
-the latex source file `mycv.tex`. We then define the `artifacts` paths which in
-turn are defined with the `paths` keyword. All paths to files and directories
-are relative to the repository that was cloned during the build.
-
-For more examples on artifacts, follow the artifacts reference in
-[`.gitlab-ci.yml` documentation](../../../ci/yaml/README.md#artifacts).
-
-## Browsing build artifacts
-
-When GitLab receives an artifacts archive, an archive metadata file is also
-generated. This metadata file describes all the entries that are located in the
-artifacts archive itself. The metadata file is in a binary format, with
-additional GZIP compression.
-
-GitLab does not extract the artifacts archive in order to save space, memory
-and disk I/O. It instead inspects the metadata file which contains all the
-relevant information. This is especially important when there is a lot of
-artifacts, or an archive is a very large file.
-
----
-
-After a build finishes, if you visit the build's specific page, you can see
-that there are two buttons. One is for downloading the artifacts archive and
-the other for browsing its contents.
-
-![Build artifacts browser button](img/build_artifacts_browser_button.png)
-
----
-
-The archive browser shows the name and the actual file size of each file in the
-archive. If your artifacts contained directories, then you are also able to
-browse inside them.
-
-Below you can see how browsing looks like. In this case we have browsed inside
-the archive and at this point there is one directory and one HTML file.
-
-![Build artifacts browser](img/build_artifacts_browser.png)
-
----
-
-## Downloading build artifacts
-
->**Note:**
-GitLab does not extract the entire artifacts archive to send just a single file
-to the user. When clicking on a specific file, [GitLab Workhorse] extracts it
-from the archive and the download begins. This implementation saves space,
-memory and disk I/O.
-
-If you need to download the whole archive, there are buttons in various places
-inside GitLab that make that possible.
-
-1. While on the pipelines page, you can see the download icon for each build's
- artifacts archive in the right corner:
-
- ![Build artifacts in Pipelines page](img/build_artifacts_pipelines_page.png)
-
-1. While on the builds page, you can see the download icon for each build's
- artifacts archive in the right corner:
-
- ![Build artifacts in Builds page](img/build_artifacts_builds_page.png)
-
-1. While inside a specific build, you are presented with a download button
- along with the one that browses the archive:
-
- ![Build artifacts browser button](img/build_artifacts_browser_button.png)
-
-1. And finally, when browsing an archive you can see the download button at
- the top right corner:
-
- ![Build artifacts browser](img/build_artifacts_browser.png)
-
-## Downloading the latest build artifacts
-
-It is possible to download the latest artifacts of a build via a well known URL
-so you can use it for scripting purposes.
-
-The structure of the URL is the following:
-
-```
-https://example.com/<namespace>/<project>/builds/artifacts/<ref>/download?job=<job_name>
-```
-
-For example, to download the latest artifacts of the job named `rspec 6 20` of
-the `master` branch of the `gitlab-ce` project that belongs to the `gitlab-org`
-namespace, the URL would be:
-
-```
-https://gitlab.com/gitlab-org/gitlab-ce/builds/artifacts/master/download?job=rspec+6+20
-```
-
-The latest builds are also exposed in the UI in various places. Specifically,
-look for the download button in:
-
-- the main project's page
-- the branches page
-- the tags page
-
-If the latest build has failed to upload the artifacts, you can see that
-information in the UI.
-
-![Latest artifacts button](img/build_latest_artifacts_browser.png)
-
-
-[gitlab workhorse]: https://gitlab.com/gitlab-org/gitlab-workhorse "GitLab Workhorse repository"
+This document was moved to [pipelines/job_artifacts](../pipelines/job_artifacts.md).
diff --git a/doc/user/project/builds/img/build_artifacts_browser.png b/doc/user/project/builds/img/build_artifacts_browser.png
deleted file mode 100644
index d95e2800c0f..00000000000
--- a/doc/user/project/builds/img/build_artifacts_browser.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/builds/img/build_artifacts_browser_button.png b/doc/user/project/builds/img/build_artifacts_browser_button.png
deleted file mode 100644
index 463540634e3..00000000000
--- a/doc/user/project/builds/img/build_artifacts_browser_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/builds/img/build_artifacts_builds_page.png b/doc/user/project/builds/img/build_artifacts_builds_page.png
deleted file mode 100644
index db78386ba7b..00000000000
--- a/doc/user/project/builds/img/build_artifacts_builds_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/builds/img/build_artifacts_pipelines_page.png b/doc/user/project/builds/img/build_artifacts_pipelines_page.png
deleted file mode 100644
index 6c2d1a4bdc7..00000000000
--- a/doc/user/project/builds/img/build_artifacts_pipelines_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/builds/img/build_latest_artifacts_browser.png b/doc/user/project/builds/img/build_latest_artifacts_browser.png
deleted file mode 100644
index d8e9071958c..00000000000
--- a/doc/user/project/builds/img/build_latest_artifacts_browser.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/container_registry.md b/doc/user/project/container_registry.md
index b205fea2c40..629d69d8aea 100644
--- a/doc/user/project/container_registry.md
+++ b/doc/user/project/container_registry.md
@@ -1,16 +1,16 @@
# GitLab Container Registry
+>**Notes:**
> [Introduced][ce-4040] in GitLab 8.8.
-
----
-
-> **Note**
-Docker Registry manifest `v1` support was added in GitLab 8.9 to support Docker
-versions earlier than 1.10.
->
-This document is about the user guide. To learn how to enable GitLab Container
-Registry across your GitLab instance, visit the
-[administrator documentation](../../administration/container_registry.md).
+- Docker Registry manifest `v1` support was added in GitLab 8.9 to support Docker
+ versions earlier than 1.10.
+- This document is about the user guide. To learn how to enable GitLab Container
+ Registry across your GitLab instance, visit the
+ [administrator documentation](../../administration/container_registry.md).
+- Starting from GitLab 8.12, if you have 2FA enabled in your account, you need
+ to pass a [personal access token][pat] instead of your password in order to
+ login to GitLab's Container Registry.
+- Multiple level image names support was added in GitLab 9.1
With the Docker Container Registry integrated into GitLab, every project can
have its own space to store its Docker images.
@@ -39,6 +39,14 @@ You can read more about Docker Registry at https://docs.docker.com/registry/intr
## Build and push images
+>**Notes:**
+- Moving or renaming existing container registry repositories is not supported
+once you have pushed images because the images are signed, and the
+signature includes the repository name.
+- To move or rename a repository with a container registry you will have to
+delete all existing images.
+
+
If you visit the **Registry** link under your project's menu, you can see the
explicit instructions to login to the Container Registry using your GitLab
credentials.
@@ -55,18 +63,25 @@ sure that you are using the Registry URL with the namespace and project name
that is hosted on GitLab:
```
-docker build -t registry.example.com/group/project .
-docker push registry.example.com/group/project
+docker build -t registry.example.com/group/project/image .
+docker push registry.example.com/group/project/image
```
Your image will be named after the following scheme:
```
-<registry URL>/<namespace>/<project>
+<registry URL>/<namespace>/<project>/<image>
```
-As such, the name of the image is unique, but you can differentiate the images
-using tags.
+GitLab supports up to three levels of image repository names.
+
+Following examples of image tags are valid:
+
+```
+registry.example.com/group/project:some-tag
+registry.example.com/group/project/image:latest
+registry.example.com/group/project/my/image:rc1
+```
## Use images from GitLab Container Registry
@@ -74,7 +89,7 @@ To download and run a container from images hosted in GitLab Container Registry,
use `docker run`:
```
-docker run [options] registry.example.com/group/project [arguments]
+docker run [options] registry.example.com/group/project/image [arguments]
```
For more information on running Docker containers, visit the
@@ -88,23 +103,22 @@ and click **Registry** in the project menu.
This view will show you all tags in your project and will easily allow you to
delete them.
-![Container Registry panel](img/container_registry_panel.png)
-
## Build and push images using GitLab CI
> **Note:**
This feature requires GitLab 8.8 and GitLab Runner 1.2.
Make sure that your GitLab Runner is configured to allow building Docker images by
-following the [Using Docker Build](../ci/docker/using_docker_build.md)
-and [Using the GitLab Container Registry documentation](../ci/docker/using_docker_build.md#using-the-gitlab-container-registry).
+following the [Using Docker Build](../../ci/docker/using_docker_build.md)
+and [Using the GitLab Container Registry documentation](../../ci/docker/using_docker_build.md#using-the-gitlab-container-registry).
+
+## Using with private projects
-## Limitations
+> [Introduced][ce-11845] in GitLab 9.3.
-In order to use a container image from your private project as an `image:` in
-your `.gitlab-ci.yml`, you have to follow the
-[Using a private Docker Registry][private-docker]
-documentation. This workflow will be simplified in the future.
+If a project is private, credentials will need to be provided for authorization.
+The preferred way to do this, is by using [personal access tokens][pat].
+The minimal scope needed is `read_registry`.
## Troubleshooting the GitLab Container Registry
@@ -137,7 +151,7 @@ A user attempted to enable an S3-backed Registry. The `docker login` step went
fine. However, when pushing an image, the output showed:
```
-The push refers to a repository [s3-testing.myregistry.com:4567/root/docker-test]
+The push refers to a repository [s3-testing.myregistry.com:4567/root/docker-test/docker-image]
dc5e59c14160: Pushing [==================================================>] 14.85 kB
03c20c1a019a: Pushing [==================================================>] 2.048 kB
a08f14ef632e: Pushing [==================================================>] 2.048 kB
@@ -230,7 +244,7 @@ a container image. You may need to run as root to do this. For example:
```sh
docker login s3-testing.myregistry.com:4567
-docker push s3-testing.myregistry.com:4567/root/docker-test
+docker push s3-testing.myregistry.com:4567/root/docker-test/docker-image
```
In the example above, we see the following trace on the mitmproxy window:
@@ -249,5 +263,6 @@ The solution: check the [IAM permissions again](https://docs.docker.com/registry
Once the right permissions were set, the error will go away.
[ce-4040]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4040
+[ce-11845]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845
[docker-docs]: https://docs.docker.com/engine/userguide/intro/
-[private-docker]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/configuration/advanced-configuration.md#using-a-private-docker-registry
+[pat]: ../profile/personal_access_tokens.md
diff --git a/doc/user/project/cycle_analytics.md b/doc/user/project/cycle_analytics.md
index c16058165d7..8f6b530c033 100644
--- a/doc/user/project/cycle_analytics.md
+++ b/doc/user/project/cycle_analytics.md
@@ -1,22 +1,19 @@
# Cycle Analytics
-> [Introduced][ce-5986] in GitLab 8.12.
->
-> **Note:**
-This the first iteration of Cycle Analytics, you can follow the following issue
-to track the changes that are coming to this feature: [#20975][ce-20975].
+> [Introduced][ce-5986] in GitLab 8.12. Further features were added in GitLab
+ 8.14.
Cycle Analytics measures the time it takes to go from an [idea to production] for
each project you have. This is achieved by not only indicating the total time it
-takes to reach at that point, but the total time is broken down into the
+takes to reach that point, but the total time is broken down into the
multiple stages an idea has to pass through to be shipped.
-Cycle Analytics is that it is tightly coupled with the [GitLab flow] and
+Cycle Analytics is tightly coupled with the [GitLab flow] and
calculates a separate median for each stage.
## Overview
-You can find the Cycle Analytics page under your project's **Pipelines > Cycle
+You can find the Cycle Analytics page under your project's **Pipelines ➔ Cycle
Analytics** tab.
![Cycle Analytics landing page](img/cycle_analytics_landing_page.png)
@@ -48,13 +45,12 @@ You can see that there are seven stages in total:
## How the data is measured
-Cycle Analytics records cycle time so only data on the issues that have been
-deployed to production are measured. In case you just started a new project and
-you have not pushed anything to production, then you will not be able to
-properly see the Cycle Analytics of your project.
+Cycle Analytics records cycle time and data based on the project issues with the
+exception of the staging and production stages, where only data deployed to
+production are measured.
Specifically, if your CI is not set up and you have not defined a `production`
-[environment], then you will not have any data.
+or `production/*` [environment], then you will not have any data for those stages.
Below you can see in more detail what the various stages of Cycle Analytics mean.
@@ -65,7 +61,7 @@ Below you can see in more detail what the various stages of Cycle Analytics mean
| Code | Measures the median time between pushing a first commit (previous stage) and creating a merge request (MR) related to that commit. The key to keep the process tracked is to include the [issue closing pattern] to the description of the merge request (for example, `Closes #xxx`, where `xxx` is the number of the issue related to this merge request). If the issue closing pattern is not present in the merge request description, the MR is not considered to the measurement time of the stage. |
| Test | Measures the median time to run the entire pipeline for that project. It's related to the time GitLab CI takes to run every job for the commits pushed to that merge request defined in the previous stage. It is basically the start->finish time for all pipelines. `master` is not excluded. It does not attempt to track time for any particular stages. |
| Review | Measures the median time taken to review the merge request, between its creation and until it's merged. |
-| Staging | Measures the median time between merging the merge request until the very first deployment to production. It's tracked by the [environment] set to `production` (case-sensitive, `Production` won't work) in your GitLab CI configuration. If there isn't a `production` environment, this is not tracked. |
+| Staging | Measures the median time between merging the merge request until the very first deployment to production. It's tracked by the [environment] set to `production` or matching `production/*` (case-sensitive, `Production` won't work) in your GitLab CI configuration. If there isn't a production environment, this is not tracked. |
| Production| The sum of all time (medians) taken to run the entire process, from issue creation to deploying the code to production. |
---
@@ -76,18 +72,20 @@ Here's a little explanation of how this works behind the scenes:
`<issue, merge request>` pair, the merge request has the [issue closing pattern]
for the corresponding issue. All other issues and merge requests are **not**
considered.
-1. Then the <issue, merge request> pairs are filtered out. Any merge request
- that has **not** been deployed to production in the last XX days (specified
- by the UI - default is 90 days) prohibits these pairs from being considered.
+1. Then the <issue, merge request> pairs are filtered out by last XX days (specified
+ by the UI - default is 90 days). So it prohibits these pairs from being considered.
1. For the remaining `<issue, merge request>` pairs, we check the information that
we need for the stages, like issue creation date, merge request merge time,
etc.
To sum up, anything that doesn't follow the [GitLab flow] won't be tracked at all.
-So, if a merge request doesn't close an issue or an issue is not labeled with a
-label present in the Issue Board or assigned a milestone or a project has no
-`production` environment, the Cycle Analytics dashboard won't present any data
-at all.
+So, the Cycle Analytics dashboard won't present any data:
+- For merge requests that do not close an issue.
+- For issues not labeled with a label present in the Issue Board.
+- For issues not assigned a milestone.
+- For staging and production stages, if the project has no `production` or `production/*`
+ environment.
+
## Example workflow
diff --git a/doc/user/project/git_attributes.md b/doc/user/project/git_attributes.md
new file mode 100644
index 00000000000..21ef94e61f7
--- /dev/null
+++ b/doc/user/project/git_attributes.md
@@ -0,0 +1,22 @@
+# Git Attributes
+
+GitLab supports defining custom [Git attributes][gitattributes] such as what
+files to treat as binary, and what language to use for syntax highlighting
+diffs.
+
+To define these attributes, create a file called `.gitattributes` in the root
+directory of your repository and push it to the default branch of your project.
+
+## Encoding Requirements
+
+The `.gitattributes` file _must_ be encoded in UTF-8 and _must not_ contain a
+Byte Order Mark. If a different encoding is used, the file's contents will be
+ignored.
+
+## Syntax Highlighting
+
+The `.gitattributes` file can be used to define which language to use when
+syntax highlighting files and diffs. See ["Syntax
+Highlighting"](highlighting.md) for more information.
+
+[gitattributes]: https://git-scm.com/docs/gitattributes
diff --git a/doc/user/project/img/container_registry_enable.png b/doc/user/project/img/container_registry_enable.png
index 6fffa2a91d8..d067a8be1ca 100644
--- a/doc/user/project/img/container_registry_enable.png
+++ b/doc/user/project/img/container_registry_enable.png
Binary files differ
diff --git a/doc/user/project/img/container_registry_panel.png b/doc/user/project/img/container_registry_panel.png
deleted file mode 100644
index 60fd76192b7..00000000000
--- a/doc/user/project/img/container_registry_panel.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/container_registry_tab.png b/doc/user/project/img/container_registry_tab.png
index 36b883aaa97..a85237271d9 100644
--- a/doc/user/project/img/container_registry_tab.png
+++ b/doc/user/project/img/container_registry_tab.png
Binary files differ
diff --git a/doc/user/project/img/cycle_analytics_landing_page.png b/doc/user/project/img/cycle_analytics_landing_page.png
index b212134d5ed..316612c0da0 100644
--- a/doc/user/project/img/cycle_analytics_landing_page.png
+++ b/doc/user/project/img/cycle_analytics_landing_page.png
Binary files differ
diff --git a/doc/user/project/img/description_templates.png b/doc/user/project/img/description_templates.png
index c41cc77a94c..e9d45029532 100644
--- a/doc/user/project/img/description_templates.png
+++ b/doc/user/project/img/description_templates.png
Binary files differ
diff --git a/doc/user/project/img/issue_board.png b/doc/user/project/img/issue_board.png
index 63c269f6dbc..b636cb294b8 100644
--- a/doc/user/project/img/issue_board.png
+++ b/doc/user/project/img/issue_board.png
Binary files differ
diff --git a/doc/user/project/img/issue_board_add_list.png b/doc/user/project/img/issue_board_add_list.png
index 2b8c10eaa0a..cdfc466d23f 100644
--- a/doc/user/project/img/issue_board_add_list.png
+++ b/doc/user/project/img/issue_board_add_list.png
Binary files differ
diff --git a/doc/user/project/img/issue_board_search_backlog.png b/doc/user/project/img/issue_board_search_backlog.png
deleted file mode 100644
index 112ea171539..00000000000
--- a/doc/user/project/img/issue_board_search_backlog.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/issue_board_system_notes.png b/doc/user/project/img/issue_board_system_notes.png
index b69ef034954..bd0f5f54095 100644
--- a/doc/user/project/img/issue_board_system_notes.png
+++ b/doc/user/project/img/issue_board_system_notes.png
Binary files differ
diff --git a/doc/user/project/img/issue_board_welcome_message.png b/doc/user/project/img/issue_board_welcome_message.png
index b757faeb230..5318e6ea4a9 100644
--- a/doc/user/project/img/issue_board_welcome_message.png
+++ b/doc/user/project/img/issue_board_welcome_message.png
Binary files differ
diff --git a/doc/user/project/img/issue_boards_add_issues_modal.png b/doc/user/project/img/issue_boards_add_issues_modal.png
new file mode 100644
index 00000000000..33049dce74f
--- /dev/null
+++ b/doc/user/project/img/issue_boards_add_issues_modal.png
Binary files differ
diff --git a/doc/user/project/img/issue_boards_remove_issue.png b/doc/user/project/img/issue_boards_remove_issue.png
new file mode 100644
index 00000000000..8b3beca97cf
--- /dev/null
+++ b/doc/user/project/img/issue_boards_remove_issue.png
Binary files differ
diff --git a/doc/user/project/img/koding_build-in-progress.png b/doc/user/project/img/koding_build-in-progress.png
index f8cc81834c4..79b7b2f10a2 100644
--- a/doc/user/project/img/koding_build-in-progress.png
+++ b/doc/user/project/img/koding_build-in-progress.png
Binary files differ
diff --git a/doc/user/project/img/koding_build-logs.png b/doc/user/project/img/koding_build-logs.png
index a04cd5aff99..b30c8375b20 100644
--- a/doc/user/project/img/koding_build-logs.png
+++ b/doc/user/project/img/koding_build-logs.png
Binary files differ
diff --git a/doc/user/project/img/koding_build-success.png b/doc/user/project/img/koding_build-success.png
index 2a0dd296480..a2342cfd324 100644
--- a/doc/user/project/img/koding_build-success.png
+++ b/doc/user/project/img/koding_build-success.png
Binary files differ
diff --git a/doc/user/project/img/koding_commit-koding.yml.png b/doc/user/project/img/koding_commit-koding.yml.png
index 3e133c50327..16842410ae2 100644
--- a/doc/user/project/img/koding_commit-koding.yml.png
+++ b/doc/user/project/img/koding_commit-koding.yml.png
Binary files differ
diff --git a/doc/user/project/img/koding_different-stack-on-mr-try.png b/doc/user/project/img/koding_different-stack-on-mr-try.png
index fd25e32f648..10c7c51d2e6 100644
--- a/doc/user/project/img/koding_different-stack-on-mr-try.png
+++ b/doc/user/project/img/koding_different-stack-on-mr-try.png
Binary files differ
diff --git a/doc/user/project/img/koding_edit-on-ide.png b/doc/user/project/img/koding_edit-on-ide.png
index fd5aaff75f5..ab861281d3e 100644
--- a/doc/user/project/img/koding_edit-on-ide.png
+++ b/doc/user/project/img/koding_edit-on-ide.png
Binary files differ
diff --git a/doc/user/project/img/koding_enable-koding.png b/doc/user/project/img/koding_enable-koding.png
index c0ae0ee9918..0b6fcfadcc5 100644
--- a/doc/user/project/img/koding_enable-koding.png
+++ b/doc/user/project/img/koding_enable-koding.png
Binary files differ
diff --git a/doc/user/project/img/koding_landing.png b/doc/user/project/img/koding_landing.png
index 7c629d9b05e..1eeddcd3813 100644
--- a/doc/user/project/img/koding_landing.png
+++ b/doc/user/project/img/koding_landing.png
Binary files differ
diff --git a/doc/user/project/img/koding_open-gitlab-from-koding.png b/doc/user/project/img/koding_open-gitlab-from-koding.png
index c958cf8f224..4235a72b36f 100644
--- a/doc/user/project/img/koding_open-gitlab-from-koding.png
+++ b/doc/user/project/img/koding_open-gitlab-from-koding.png
Binary files differ
diff --git a/doc/user/project/img/koding_run-in-ide.png b/doc/user/project/img/koding_run-in-ide.png
index f91ee0f74cc..d22e5023c59 100644
--- a/doc/user/project/img/koding_run-in-ide.png
+++ b/doc/user/project/img/koding_run-in-ide.png
Binary files differ
diff --git a/doc/user/project/img/koding_run-mr-in-ide.png b/doc/user/project/img/koding_run-mr-in-ide.png
index 502817a2a46..cb1112c4034 100644
--- a/doc/user/project/img/koding_run-mr-in-ide.png
+++ b/doc/user/project/img/koding_run-mr-in-ide.png
Binary files differ
diff --git a/doc/user/project/img/koding_set-up-ide.png b/doc/user/project/img/koding_set-up-ide.png
index 7f408c980b5..033d41729a2 100644
--- a/doc/user/project/img/koding_set-up-ide.png
+++ b/doc/user/project/img/koding_set-up-ide.png
Binary files differ
diff --git a/doc/user/project/img/koding_stack-import.png b/doc/user/project/img/koding_stack-import.png
index 2a4e3c87fc8..245ccb07ba3 100644
--- a/doc/user/project/img/koding_stack-import.png
+++ b/doc/user/project/img/koding_stack-import.png
Binary files differ
diff --git a/doc/user/project/img/koding_start-build.png b/doc/user/project/img/koding_start-build.png
index 52159440f62..3f5c16d5d2f 100644
--- a/doc/user/project/img/koding_start-build.png
+++ b/doc/user/project/img/koding_start-build.png
Binary files differ
diff --git a/doc/user/project/img/labels_assign_label_in_new_issue.png b/doc/user/project/img/labels_assign_label_in_new_issue.png
index e32a35f7cda..badfbed0bbe 100644
--- a/doc/user/project/img/labels_assign_label_in_new_issue.png
+++ b/doc/user/project/img/labels_assign_label_in_new_issue.png
Binary files differ
diff --git a/doc/user/project/img/labels_assign_label_sidebar.png b/doc/user/project/img/labels_assign_label_sidebar.png
index 799443af889..d74796fdb4d 100644
--- a/doc/user/project/img/labels_assign_label_sidebar.png
+++ b/doc/user/project/img/labels_assign_label_sidebar.png
Binary files differ
diff --git a/doc/user/project/img/labels_assign_label_sidebar_saved.png b/doc/user/project/img/labels_assign_label_sidebar_saved.png
index e7d8d69e60e..dabffe956dc 100644
--- a/doc/user/project/img/labels_assign_label_sidebar_saved.png
+++ b/doc/user/project/img/labels_assign_label_sidebar_saved.png
Binary files differ
diff --git a/doc/user/project/img/labels_default.png b/doc/user/project/img/labels_default.png
index ee0c9f889ad..474953d565b 100644
--- a/doc/user/project/img/labels_default.png
+++ b/doc/user/project/img/labels_default.png
Binary files differ
diff --git a/doc/user/project/img/labels_description_tooltip.png b/doc/user/project/img/labels_description_tooltip.png
index 0d1e3e091fb..eea4f8cf0f4 100644
--- a/doc/user/project/img/labels_description_tooltip.png
+++ b/doc/user/project/img/labels_description_tooltip.png
Binary files differ
diff --git a/doc/user/project/img/labels_filter.png b/doc/user/project/img/labels_filter.png
index ed622be2d93..3aca77f0070 100644
--- a/doc/user/project/img/labels_filter.png
+++ b/doc/user/project/img/labels_filter.png
Binary files differ
diff --git a/doc/user/project/img/labels_filter_by_priority.png b/doc/user/project/img/labels_filter_by_priority.png
index c5a9e20919b..5609a1f6d7f 100644
--- a/doc/user/project/img/labels_filter_by_priority.png
+++ b/doc/user/project/img/labels_filter_by_priority.png
Binary files differ
diff --git a/doc/user/project/img/labels_generate.png b/doc/user/project/img/labels_generate.png
index 9579be4e231..987f4b5be71 100644
--- a/doc/user/project/img/labels_generate.png
+++ b/doc/user/project/img/labels_generate.png
Binary files differ
diff --git a/doc/user/project/img/labels_new_label.png b/doc/user/project/img/labels_new_label.png
index a916d3dceb5..b44b4bd296d 100644
--- a/doc/user/project/img/labels_new_label.png
+++ b/doc/user/project/img/labels_new_label.png
Binary files differ
diff --git a/doc/user/project/img/labels_new_label_on_the_fly.png b/doc/user/project/img/labels_new_label_on_the_fly.png
index 80cc434239e..2ac9805b1ab 100644
--- a/doc/user/project/img/labels_new_label_on_the_fly.png
+++ b/doc/user/project/img/labels_new_label_on_the_fly.png
Binary files differ
diff --git a/doc/user/project/img/labels_new_label_on_the_fly_create.png b/doc/user/project/img/labels_new_label_on_the_fly_create.png
index c41090945eb..02ccf68553b 100644
--- a/doc/user/project/img/labels_new_label_on_the_fly_create.png
+++ b/doc/user/project/img/labels_new_label_on_the_fly_create.png
Binary files differ
diff --git a/doc/user/project/img/labels_prioritize.png b/doc/user/project/img/labels_prioritize.png
index 8dfe72cf826..3e888f36364 100644
--- a/doc/user/project/img/labels_prioritize.png
+++ b/doc/user/project/img/labels_prioritize.png
Binary files differ
diff --git a/doc/user/project/img/labels_subscribe.png b/doc/user/project/img/labels_subscribe.png
index ea3db2bc0cf..56f24ae7bc8 100644
--- a/doc/user/project/img/labels_subscribe.png
+++ b/doc/user/project/img/labels_subscribe.png
Binary files differ
diff --git a/doc/user/project/img/mitmproxy-docker.png b/doc/user/project/img/mitmproxy-docker.png
index 4e3e37b413d..aa3b6a0b830 100644
--- a/doc/user/project/img/mitmproxy-docker.png
+++ b/doc/user/project/img/mitmproxy-docker.png
Binary files differ
diff --git a/doc/user/project/img/project_repository_settings.png b/doc/user/project/img/project_repository_settings.png
new file mode 100644
index 00000000000..1aa7efc36f1
--- /dev/null
+++ b/doc/user/project/img/project_repository_settings.png
Binary files differ
diff --git a/doc/user/project/img/project_settings_list.png b/doc/user/project/img/project_settings_list.png
deleted file mode 100644
index 57ca2ac5f9e..00000000000
--- a/doc/user/project/img/project_settings_list.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/protected_branches_choose_branch.png b/doc/user/project/img/protected_branches_choose_branch.png
index 26328143717..c2848db9c96 100644
--- a/doc/user/project/img/protected_branches_choose_branch.png
+++ b/doc/user/project/img/protected_branches_choose_branch.png
Binary files differ
diff --git a/doc/user/project/img/protected_branches_delete.png b/doc/user/project/img/protected_branches_delete.png
new file mode 100644
index 00000000000..cfdfe6c6c29
--- /dev/null
+++ b/doc/user/project/img/protected_branches_delete.png
Binary files differ
diff --git a/doc/user/project/img/protected_branches_devs_can_push.png b/doc/user/project/img/protected_branches_devs_can_push.png
index 812cc8767b7..320e6eb7fee 100644
--- a/doc/user/project/img/protected_branches_devs_can_push.png
+++ b/doc/user/project/img/protected_branches_devs_can_push.png
Binary files differ
diff --git a/doc/user/project/img/protected_branches_error_ui.png b/doc/user/project/img/protected_branches_error_ui.png
index cc61df7ca97..3f8e462d3ad 100644
--- a/doc/user/project/img/protected_branches_error_ui.png
+++ b/doc/user/project/img/protected_branches_error_ui.png
Binary files differ
diff --git a/doc/user/project/img/protected_branches_list.png b/doc/user/project/img/protected_branches_list.png
index f33f1b2bdb6..1b2936cb711 100644
--- a/doc/user/project/img/protected_branches_list.png
+++ b/doc/user/project/img/protected_branches_list.png
Binary files differ
diff --git a/doc/user/project/img/protected_branches_matches.png b/doc/user/project/img/protected_branches_matches.png
index 30ce53f704e..d7f2c8582fc 100644
--- a/doc/user/project/img/protected_branches_matches.png
+++ b/doc/user/project/img/protected_branches_matches.png
Binary files differ
diff --git a/doc/user/project/img/protected_branches_page.png b/doc/user/project/img/protected_branches_page.png
index 1585dde5b29..4e5afff3bae 100644
--- a/doc/user/project/img/protected_branches_page.png
+++ b/doc/user/project/img/protected_branches_page.png
Binary files differ
diff --git a/doc/user/project/img/protected_tag_matches.png b/doc/user/project/img/protected_tag_matches.png
new file mode 100644
index 00000000000..a36a11a1271
--- /dev/null
+++ b/doc/user/project/img/protected_tag_matches.png
Binary files differ
diff --git a/doc/user/project/img/protected_tags_list.png b/doc/user/project/img/protected_tags_list.png
new file mode 100644
index 00000000000..c5e42dc0705
--- /dev/null
+++ b/doc/user/project/img/protected_tags_list.png
Binary files differ
diff --git a/doc/user/project/img/protected_tags_page.png b/doc/user/project/img/protected_tags_page.png
new file mode 100644
index 00000000000..3848d91ebd6
--- /dev/null
+++ b/doc/user/project/img/protected_tags_page.png
Binary files differ
diff --git a/doc/user/project/img/protected_tags_permissions_dropdown.png b/doc/user/project/img/protected_tags_permissions_dropdown.png
new file mode 100644
index 00000000000..9e0fc4e2a43
--- /dev/null
+++ b/doc/user/project/img/protected_tags_permissions_dropdown.png
Binary files differ
diff --git a/doc/user/project/integrations/bamboo.md b/doc/user/project/integrations/bamboo.md
new file mode 100644
index 00000000000..1e28646bc97
--- /dev/null
+++ b/doc/user/project/integrations/bamboo.md
@@ -0,0 +1,59 @@
+# Atlassian Bamboo CI Service
+
+GitLab provides integration with Atlassian Bamboo for continuous integration.
+When configured, pushes to a project will trigger a build in Bamboo automatically.
+Merge requests will also display CI status showing whether the build is pending,
+failed, or completed successfully. It also provides a link to the Bamboo build
+page for more information.
+
+Bamboo doesn't quite provide the same features as a traditional build system when
+it comes to accepting webhooks and commit data. There are a few things that
+need to be configured in a Bamboo build plan before GitLab can integrate.
+
+## Setup
+
+### Complete these steps in Bamboo
+
+1. Navigate to a Bamboo build plan and choose 'Configure plan' from the 'Actions'
+ dropdown.
+1. Select the 'Triggers' tab.
+1. Click 'Add trigger'.
+1. Enter a description such as 'GitLab trigger'
+1. Choose 'Repository triggers the build when changes are committed'
+1. Check one or more repositories checkboxes
+1. Enter the GitLab IP address in the 'Trigger IP addresses' box. This is a
+ whitelist of IP addresses that are allowed to trigger Bamboo builds.
+1. Save the trigger.
+1. In the left pane, select a build stage. If you have multiple build stages
+ you want to select the last stage that contains the git checkout task.
+1. Select the 'Miscellaneous' tab.
+1. Under 'Pattern Match Labelling' put '${bamboo.repository.revision.number}'
+ in the 'Labels' box.
+1. Save
+
+Bamboo is now ready to accept triggers from GitLab. Next, set up the Bamboo
+service in GitLab.
+
+### Complete these steps in GitLab
+
+1. Navigate to the project you want to configure to trigger builds.
+1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
+1. Click 'Atlassian Bamboo CI'
+1. Select the 'Active' checkbox.
+1. Enter the base URL of your Bamboo server. 'https://bamboo.example.com'
+1. Enter the build key from your Bamboo build plan. Build keys are a short,
+ all capital letter, identifier that is unique. It will be something like PR-BLD
+1. If necessary, enter username and password for a Bamboo user that has
+ access to trigger the build plan. Leave these fields blank if you do not require
+ authentication.
+1. Save or optionally click 'Test Settings'. Please note that 'Test Settings'
+ will actually trigger a build in Bamboo.
+
+## Troubleshooting
+
+If builds are not triggered, ensure you entered the right GitLab IP address in
+Bamboo under 'Trigger IP addresses'.
+
+>**Note:**
+- Starting with GitLab 8.14.0, builds are triggered on push events.
+
diff --git a/doc/user/project/integrations/bugzilla.md b/doc/user/project/integrations/bugzilla.md
new file mode 100644
index 00000000000..0b219e84478
--- /dev/null
+++ b/doc/user/project/integrations/bugzilla.md
@@ -0,0 +1,18 @@
+# Bugzilla Service
+
+Navigate to the [Integrations page](project_services.md#accessing-the-project-services),
+select the **Bugzilla** service and fill in the required details as described
+in the table below.
+
+| Field | Description |
+| ----- | ----------- |
+| `description` | A name for the issue tracker (to differentiate between instances, for example) |
+| `project_url` | The URL to the project in Bugzilla which is being linked to this GitLab project. Note that the `project_url` requires PRODUCT_NAME to be updated with the product/project name in Bugzilla. |
+| `issues_url` | The URL to the issue in Bugzilla project that is linked to this GitLab project. Note that the `issues_url` requires `:id` in the URL. This ID is used by GitLab as a placeholder to replace the issue number. |
+| `new_issue_url` | This is the URL to create a new issue in Bugzilla for the project linked to this GitLab project. Note that the `new_issue_url` requires PRODUCT_NAME to be updated with the product/project name in Bugzilla. |
+
+Once you have configured and enabled Bugzilla:
+
+- the **Issues** link on the GitLab project pages takes you to the appropriate
+ Bugzilla product page
+- clicking **New issue** on the project dashboard takes you to Bugzilla for entering a new issue
diff --git a/doc/user/project/integrations/emails_on_push.md b/doc/user/project/integrations/emails_on_push.md
new file mode 100644
index 00000000000..18109fc049c
--- /dev/null
+++ b/doc/user/project/integrations/emails_on_push.md
@@ -0,0 +1,20 @@
+# Enabling emails on push
+
+By enabling this service, you will be able to receive email notifications for
+every change that is pushed to your project.
+
+Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
+and select the **Emails on push** service to configure it.
+
+In the _Recipients_ area, provide a list of emails separated by commas.
+
+You can configure any of the following settings depending on your preference.
+
++ **Push events** - Email will be triggered when a push event is recieved
++ **Tag push events** - Email will be triggered when a tag is created and pushed
++ **Send from committer** - Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. `user@gitlab.com`).
++ **Disable code diffs** - Don't include possibly sensitive code diffs in notification body.
+
+---
+
+![Email on push service settings](img/emails_on_push_service.png)
diff --git a/doc/user/project/integrations/hipchat.md b/doc/user/project/integrations/hipchat.md
new file mode 100644
index 00000000000..eee779c50d4
--- /dev/null
+++ b/doc/user/project/integrations/hipchat.md
@@ -0,0 +1,53 @@
+# Atlassian HipChat
+
+GitLab provides a way to send HipChat notifications upon a number of events,
+such as when a user pushes code, creates a branch or tag, adds a comment, and
+creates a merge request.
+
+## Setup
+
+GitLab requires the use of a HipChat v2 API token to work. v1 tokens are
+not supported at this time. Note the differences between v1 and v2 tokens:
+
+HipChat v1 API (legacy) supports "API Auth Tokens" in the Group API menu. A v1
+token is allowed to send messages to *any* room.
+
+HipChat v2 API has tokens that are can be created using the Integrations tab
+in the Group or Room admin page. By design, these are lightweight tokens that
+allow GitLab to send messages only to *one* room.
+
+### Complete these steps in HipChat
+
+1. Go to: https://admin.hipchat.com/admin
+1. Click on "Group Admin" -> "Integrations".
+1. Find "Build Your Own!" and click "Create".
+1. Select the desired room, name the integration "GitLab", and click "Create".
+1. In the "Send messages to this room by posting this URL" column, you should
+see a URL in the format:
+
+```
+https://api.hipchat.com/v2/room/<room>/notification?auth_token=<token>
+```
+
+HipChat is now ready to accept messages from GitLab. Next, set up the HipChat
+service in GitLab.
+
+### Complete these steps in GitLab
+
+1. Navigate to the project you want to configure for notifications.
+1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
+1. Click "HipChat".
+1. Select the "Active" checkbox.
+1. Insert the `token` field from the URL into the `Token` field on the Web page.
+1. Insert the `room` field from the URL into the `Room` field on the Web page.
+1. Save or optionally click "Test Settings".
+
+## Troubleshooting
+
+If you do not see notifications, make sure you are using a HipChat v2 API
+token, not a v1 token.
+
+Note that the v2 token is tied to a specific room. If you want to be able to
+specify arbitrary rooms, you can create an API token for a specific user in
+HipChat under "Account settings" and "API access". Use the `XXX` value under
+`auth_token=XXX`.
diff --git a/doc/user/project/integrations/img/emails_on_push_service.png b/doc/user/project/integrations/img/emails_on_push_service.png
new file mode 100644
index 00000000000..df301aa1eeb
--- /dev/null
+++ b/doc/user/project/integrations/img/emails_on_push_service.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_add_user_to_group.png b/doc/user/project/integrations/img/jira_add_user_to_group.png
new file mode 100644
index 00000000000..27dac49260c
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_add_user_to_group.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_create_new_group.png b/doc/user/project/integrations/img/jira_create_new_group.png
new file mode 100644
index 00000000000..06c4e84fc61
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_create_new_group.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_create_new_group_name.png b/doc/user/project/integrations/img/jira_create_new_group_name.png
new file mode 100644
index 00000000000..bfc0dc6b2e9
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_create_new_group_name.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_create_new_user.png b/doc/user/project/integrations/img/jira_create_new_user.png
new file mode 100644
index 00000000000..e9c03ed770d
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_create_new_user.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_group_access.png b/doc/user/project/integrations/img/jira_group_access.png
new file mode 100644
index 00000000000..9d64cc57269
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_group_access.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_issue_reference.png b/doc/user/project/integrations/img/jira_issue_reference.png
new file mode 100644
index 00000000000..72c81460df7
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_issue_reference.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_merge_request_close.png b/doc/user/project/integrations/img/jira_merge_request_close.png
new file mode 100644
index 00000000000..0f82ceba557
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_merge_request_close.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_project_name.png b/doc/user/project/integrations/img/jira_project_name.png
new file mode 100644
index 00000000000..8540a427461
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_project_name.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_project_settings.png b/doc/user/project/integrations/img/jira_project_settings.png
new file mode 100644
index 00000000000..cb6a6ba14ce
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_project_settings.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_service.png b/doc/user/project/integrations/img/jira_service.png
new file mode 100644
index 00000000000..8e073b84ff9
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_service.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_service_close_comment.png b/doc/user/project/integrations/img/jira_service_close_comment.png
new file mode 100644
index 00000000000..bb9cd7e3d13
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_service_close_comment.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_service_close_issue.png b/doc/user/project/integrations/img/jira_service_close_issue.png
new file mode 100644
index 00000000000..c85b1d1dd97
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_service_close_issue.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_service_page.png b/doc/user/project/integrations/img/jira_service_page.png
new file mode 100644
index 00000000000..e69376f74c4
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_service_page.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_user_management_link.png b/doc/user/project/integrations/img/jira_user_management_link.png
new file mode 100644
index 00000000000..f81c5b5fc87
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_user_management_link.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_workflow_screenshot.png b/doc/user/project/integrations/img/jira_workflow_screenshot.png
new file mode 100644
index 00000000000..e62fb202613
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_workflow_screenshot.png
Binary files differ
diff --git a/doc/user/project/integrations/img/kubernetes_configuration.png b/doc/user/project/integrations/img/kubernetes_configuration.png
new file mode 100644
index 00000000000..349a2dc8456
--- /dev/null
+++ b/doc/user/project/integrations/img/kubernetes_configuration.png
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_add_slash_command.png b/doc/user/project/integrations/img/mattermost_add_slash_command.png
new file mode 100644
index 00000000000..7759efa183c
--- /dev/null
+++ b/doc/user/project/integrations/img/mattermost_add_slash_command.png
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_bot_auth.png b/doc/user/project/integrations/img/mattermost_bot_auth.png
new file mode 100644
index 00000000000..830b7849f3d
--- /dev/null
+++ b/doc/user/project/integrations/img/mattermost_bot_auth.png
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_bot_available_commands.png b/doc/user/project/integrations/img/mattermost_bot_available_commands.png
new file mode 100644
index 00000000000..b51798cf10d
--- /dev/null
+++ b/doc/user/project/integrations/img/mattermost_bot_available_commands.png
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_config_help.png b/doc/user/project/integrations/img/mattermost_config_help.png
new file mode 100644
index 00000000000..dd3481bc1f6
--- /dev/null
+++ b/doc/user/project/integrations/img/mattermost_config_help.png
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_configuration.png b/doc/user/project/integrations/img/mattermost_configuration.png
new file mode 100644
index 00000000000..f52acf4ef3b
--- /dev/null
+++ b/doc/user/project/integrations/img/mattermost_configuration.png
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_console_integrations.png b/doc/user/project/integrations/img/mattermost_console_integrations.png
new file mode 100644
index 00000000000..92a30da5be0
--- /dev/null
+++ b/doc/user/project/integrations/img/mattermost_console_integrations.png
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_gitlab_token.png b/doc/user/project/integrations/img/mattermost_gitlab_token.png
new file mode 100644
index 00000000000..257018914d2
--- /dev/null
+++ b/doc/user/project/integrations/img/mattermost_gitlab_token.png
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_goto_console.png b/doc/user/project/integrations/img/mattermost_goto_console.png
new file mode 100644
index 00000000000..3354c2a24b4
--- /dev/null
+++ b/doc/user/project/integrations/img/mattermost_goto_console.png
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_slash_command_configuration.png b/doc/user/project/integrations/img/mattermost_slash_command_configuration.png
new file mode 100644
index 00000000000..12766ab2b34
--- /dev/null
+++ b/doc/user/project/integrations/img/mattermost_slash_command_configuration.png
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_slash_command_token.png b/doc/user/project/integrations/img/mattermost_slash_command_token.png
new file mode 100644
index 00000000000..c38f37c203c
--- /dev/null
+++ b/doc/user/project/integrations/img/mattermost_slash_command_token.png
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_team_integrations.png b/doc/user/project/integrations/img/mattermost_team_integrations.png
new file mode 100644
index 00000000000..69d4a231e5a
--- /dev/null
+++ b/doc/user/project/integrations/img/mattermost_team_integrations.png
Binary files differ
diff --git a/doc/user/project/integrations/img/merge_request_performance.png b/doc/user/project/integrations/img/merge_request_performance.png
new file mode 100644
index 00000000000..eba6515a6ae
--- /dev/null
+++ b/doc/user/project/integrations/img/merge_request_performance.png
Binary files differ
diff --git a/doc/user/project/integrations/img/microsoft_teams_configuration.png b/doc/user/project/integrations/img/microsoft_teams_configuration.png
new file mode 100644
index 00000000000..b5c9efc3dd9
--- /dev/null
+++ b/doc/user/project/integrations/img/microsoft_teams_configuration.png
Binary files differ
diff --git a/doc/user/project/integrations/img/project_services.png b/doc/user/project/integrations/img/project_services.png
new file mode 100644
index 00000000000..25b6cd5690b
--- /dev/null
+++ b/doc/user/project/integrations/img/project_services.png
Binary files differ
diff --git a/doc/user/project/integrations/img/prometheus_gcp_firewall_rule.png b/doc/user/project/integrations/img/prometheus_gcp_firewall_rule.png
new file mode 100644
index 00000000000..e30cba211e6
--- /dev/null
+++ b/doc/user/project/integrations/img/prometheus_gcp_firewall_rule.png
Binary files differ
diff --git a/doc/user/project/integrations/img/prometheus_gcp_node_name.png b/doc/user/project/integrations/img/prometheus_gcp_node_name.png
new file mode 100644
index 00000000000..ea289431454
--- /dev/null
+++ b/doc/user/project/integrations/img/prometheus_gcp_node_name.png
Binary files differ
diff --git a/doc/user/project/integrations/img/prometheus_service_configuration.png b/doc/user/project/integrations/img/prometheus_service_configuration.png
new file mode 100644
index 00000000000..c7dfe874817
--- /dev/null
+++ b/doc/user/project/integrations/img/prometheus_service_configuration.png
Binary files differ
diff --git a/doc/user/project/integrations/img/prometheus_yaml_deploy.png b/doc/user/project/integrations/img/prometheus_yaml_deploy.png
new file mode 100644
index 00000000000..978cd7eaa50
--- /dev/null
+++ b/doc/user/project/integrations/img/prometheus_yaml_deploy.png
Binary files differ
diff --git a/doc/user/project/integrations/img/redmine_configuration.png b/doc/user/project/integrations/img/redmine_configuration.png
new file mode 100644
index 00000000000..7b6dd271401
--- /dev/null
+++ b/doc/user/project/integrations/img/redmine_configuration.png
Binary files differ
diff --git a/doc/user/project/integrations/img/services_templates_redmine_example.png b/doc/user/project/integrations/img/services_templates_redmine_example.png
new file mode 100644
index 00000000000..379cef9888d
--- /dev/null
+++ b/doc/user/project/integrations/img/services_templates_redmine_example.png
Binary files differ
diff --git a/doc/user/project/integrations/img/slack_configuration.png b/doc/user/project/integrations/img/slack_configuration.png
new file mode 100644
index 00000000000..527824fc3eb
--- /dev/null
+++ b/doc/user/project/integrations/img/slack_configuration.png
Binary files differ
diff --git a/doc/user/project/integrations/img/slack_setup.png b/doc/user/project/integrations/img/slack_setup.png
new file mode 100644
index 00000000000..7928fb7d495
--- /dev/null
+++ b/doc/user/project/integrations/img/slack_setup.png
Binary files differ
diff --git a/doc/user/project/integrations/img/webhook_logs.png b/doc/user/project/integrations/img/webhook_logs.png
new file mode 100755
index 00000000000..917068d9398
--- /dev/null
+++ b/doc/user/project/integrations/img/webhook_logs.png
Binary files differ
diff --git a/doc/user/project/integrations/img/webhooks_ssl.png b/doc/user/project/integrations/img/webhooks_ssl.png
new file mode 100644
index 00000000000..21ddec4ebdf
--- /dev/null
+++ b/doc/user/project/integrations/img/webhooks_ssl.png
Binary files differ
diff --git a/doc/user/project/integrations/index.md b/doc/user/project/integrations/index.md
new file mode 100644
index 00000000000..e384ed57de9
--- /dev/null
+++ b/doc/user/project/integrations/index.md
@@ -0,0 +1,24 @@
+# Project integrations
+
+You can find the available integrations under your project's
+**Settings ➔ Integrations** page. You need to have at least
+[master permission][permissions] on the project.
+
+## Project services
+
+Project services allow you to integrate GitLab with other applications.
+They are a bit like plugins in that they allow a lot of freedom in
+adding functionality to GitLab.
+
+[Learn more about project services.](project_services.md)
+
+## Project webhooks
+
+Project webhooks allow you to trigger a URL if for example new code is pushed or
+a new issue is created. You can configure webhooks to listen for specific events
+like pushes, issues or merge requests. GitLab will send a POST request with data
+to the webhook URL.
+
+[Learn more about webhooks.](webhooks.md)
+
+[permissions]: ../../permissions.md
diff --git a/doc/user/project/integrations/irker.md b/doc/user/project/integrations/irker.md
new file mode 100644
index 00000000000..c63ea1316fe
--- /dev/null
+++ b/doc/user/project/integrations/irker.md
@@ -0,0 +1,50 @@
+# Irker IRC Gateway
+
+GitLab provides a way to push update messages to an Irker server. When
+configured, pushes to a project will trigger the service to send data directly
+to the Irker server.
+
+See the project homepage for further info: https://gitlab.com/esr/irker
+
+## Needed setup
+
+You will first need an Irker daemon. You can download the Irker code from its
+repository on https://gitlab.com/esr/irker:
+
+```
+git clone https://gitlab.com/esr/irker.git
+```
+
+Once you have downloaded the code, you can run the python script named `irkerd`.
+This script is the gateway script, it acts both as an IRC client, for sending
+messages to an IRC server obviously, and as a TCP server, for receiving messages
+from the GitLab service.
+
+If the Irker server runs on the same machine, you are done. If not, you will
+need to follow the firsts steps of the next section.
+
+## Complete these steps in GitLab
+
+1. Navigate to the project you want to configure for notifications.
+1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
+1. Click "Irker".
+1. Select the "Active" checkbox.
+1. Enter the server host address where `irkerd` runs (defaults to `localhost`)
+in the `Server host` field on the Web page
+1. Enter the server port of `irkerd` (e.g. defaults to 6659) in the
+`Server port` field on the Web page.
+1. Optional: if `Default IRC URI` is set, it has to be in the format
+`irc[s]://domain.name` and will be prepend to each and every channel provided
+by the user which is not a full URI.
+1. Specify the recipients (e.g. #channel1, user1, etc.)
+1. Save or optionally click "Test Settings".
+
+## Note on Irker recipients
+
+Irker accepts channel names of the form `chan` and `#chan`, both for the
+`#chan` channel. If you want to send messages in query, you will need to add
+`,isnick` after the channel name, in this form: `Aorimn,isnick`. In this latter
+case, `Aorimn` is treated as a nick and no more as a channel name.
+
+Irker can also join password-protected channels. Users need to append
+`?key=thesecretpassword` to the chan name.
diff --git a/doc/user/project/integrations/jira.md b/doc/user/project/integrations/jira.md
new file mode 100644
index 00000000000..cf03f2a9033
--- /dev/null
+++ b/doc/user/project/integrations/jira.md
@@ -0,0 +1,215 @@
+# GitLab JIRA integration
+
+GitLab can be configured to interact with JIRA. Configuration happens via
+user name and password. Connecting to a JIRA server via CAS is not possible.
+
+Each project can be configured to connect to a different JIRA instance, see the
+[configuration](#configuration) section. If you have one JIRA instance you can
+pre-fill the settings page with a default template. To configure the template
+see the [Services Templates][services-templates] document.
+
+Once the project is connected to JIRA, you can reference and close the issues
+in JIRA directly from GitLab.
+
+## Configuration
+
+In order to enable the JIRA service in GitLab, you need to first configure the
+project in JIRA and then enter the correct values in GitLab.
+
+### Configuring JIRA
+
+We need to create a user in JIRA which will have access to all projects that
+need to integrate with GitLab. Login to your JIRA instance as admin and under
+Administration go to User Management and create a new user.
+
+As an example, we'll create a user named `gitlab` and add it to `JIRA-developers`
+group.
+
+**It is important that the user `GitLab` has write-access to projects in JIRA**
+
+We have split this stage in steps so it is easier to follow.
+
+---
+
+1. Login to your JIRA instance as an administrator and under **Administration**
+ go to **User Management** to create a new user.
+
+ ![JIRA user management link](img/jira_user_management_link.png)
+
+ ---
+
+1. The next step is to create a new user (e.g., `gitlab`) who has write access
+ to projects in JIRA. Enter the user's name and a _valid_ e-mail address
+ since JIRA sends a verification e-mail to set-up the password.
+ _**Note:** JIRA creates the username automatically by using the e-mail
+ prefix. You can change it later if you want._
+
+ ![JIRA create new user](img/jira_create_new_user.png)
+
+ ---
+
+1. Now, let's create a `gitlab-developers` group which will have write access
+ to projects in JIRA. Go to the **Groups** tab and select **Create group**.
+
+ ![JIRA create new user](img/jira_create_new_group.png)
+
+ ---
+
+ Give it an optional description and hit **Create group**.
+
+ ![jira create new group](img/jira_create_new_group_name.png)
+
+ ---
+
+1. Give the newly-created group write access by going to
+ **Application access ➔ View configuration** and adding the `gitlab-developers`
+ group to JIRA Core.
+
+ ![JIRA group access](img/jira_group_access.png)
+
+ ---
+
+1. Add the `gitlab` user to the `gitlab-developers` group by going to
+ **Users ➔ GitLab user ➔ Add group** and selecting the `gitlab-developers`
+ group from the dropdown menu. Notice that the group says _Access_ which is
+ what we aim for.
+
+ ![JIRA add user to group](img/jira_add_user_to_group.png)
+
+ ---
+
+The JIRA configuration is over. Write down the new JIRA username and its
+password as they will be needed when configuring GitLab in the next section.
+
+### Configuring GitLab
+
+>**Notes:**
+- The currently supported JIRA versions are `v6.x` and `v7.x.`. GitLab 7.8 or
+ higher is required.
+- GitLab 8.14 introduced a new way to integrate with JIRA which greatly simplified
+ the configuration options you have to enter. If you are using an older version,
+ [follow this documentation][jira-repo-old-docs].
+
+To enable JIRA integration in a project, navigate to the
+[Integrations page](project_services.md#accessing-the-project-services), click
+the **JIRA** service, and fill in the required details on the page as described
+in the table below.
+
+| Field | Description |
+| ----- | ----------- |
+| `Web URL` | The base URL to the JIRA instance web interface which is being linked to this GitLab project. E.g., `https://jira.example.com`. |
+| `JIRA API URL` | The base URL to the JIRA instance API. E.g., `https://jira-api.example.com`. This is optional. If not entered, the Web URL value be used. |
+| `Project key` | Put a JIRA project key (in uppercase), e.g. `MARS` in this field. This is only for testing the configuration settings. JIRA integration in GitLab works with _all_ JIRA projects in your JIRA instance. This field will be removed in a future release. |
+| `Username` | The user name created in [configuring JIRA step](#configuring-jira). |
+| `Password` |The password of the user created in [configuring JIRA step](#configuring-jira). |
+| `JIRA issue transition` | This is the ID of a transition that moves issues to a closed state. You can find this number under JIRA workflow administration ([see screenshot](img/jira_workflow_screenshot.png)). **Closing JIRA issues via commits or Merge Requests won't work if you don't set the ID correctly.** |
+
+After saving the configuration, your GitLab project will be able to interact
+with all JIRA projects in your JIRA instance.
+
+![JIRA service page](img/jira_service_page.png)
+
+---
+
+## JIRA issues
+
+By now you should have [configured JIRA](#configuring-jira) and enabled the
+[JIRA service in GitLab](#configuring-gitlab). If everything is set up correctly
+you should be able to reference and close JIRA issues by just mentioning their
+ID in GitLab commits and merge requests.
+
+### Referencing JIRA Issues
+
+When GitLab project has JIRA issue tracker configured and enabled, mentioning
+JIRA issue in GitLab will automatically add a comment in JIRA issue with the
+link back to GitLab. This means that in comments in merge requests and commits
+referencing an issue, e.g., `PROJECT-7`, will add a comment in JIRA issue in the
+format:
+
+```
+USER mentioned this issue in RESOURCE_NAME of [PROJECT_NAME|LINK_TO_COMMENT]:
+ENTITY_TITLE
+```
+
+* `USER` A user that mentioned the issue. This is the link to the user profile in GitLab.
+* `LINK_TO_THE_COMMENT` Link to the origin of mention with a name of the entity where JIRA issue was mentioned.
+* `RESOURCE_NAME` Kind of resource which referenced the issue. Can be a commit or merge request.
+* `PROJECT_NAME` GitLab project name.
+* `ENTITY_TITLE` Merge request title or commit message first line.
+
+![example of mentioning or closing the JIRA issue](img/jira_issue_reference.png)
+
+---
+
+### Closing JIRA Issues
+
+JIRA issues can be closed directly from GitLab by using trigger words in
+commits and merge requests. When a commit which contains the trigger word
+followed by the JIRA issue ID in the commit message is pushed, GitLab will
+add a comment in the mentioned JIRA issue and immediately close it (provided
+the transition ID was set up correctly).
+
+There are currently three trigger words, and you can use either one to achieve
+the same goal:
+
+- `Resolves PROJECT-1`
+- `Closes PROJECT-1`
+- `Fixes PROJECT-1`
+
+where `PROJECT-1` is the issue ID of the JIRA project.
+
+>**Note:**
+- Only commits and merges into the project's default branch (usually **master**) will
+ close an issue in Jira. You can change your projects default branch under
+ [project settings](img/jira_project_settings.png).
+
+### JIRA issue closing example
+
+Let's consider the following example:
+
+1. For the project named `PROJECT` in JIRA, we implemented a new feature
+ and created a merge request in GitLab.
+1. This feature was requested in JIRA issue `PROJECT-7` and the merge request
+ in GitLab contains the improvement
+1. In the merge request description we use the issue closing trigger
+ `Closes PROJECT-7`.
+1. Once the merge request is merged, the JIRA issue will be automatically closed
+ with a comment and an associated link to the commit that resolved the issue.
+
+---
+
+In the following screenshot you can see what the link references to the JIRA
+issue look like.
+
+![A Git commit that causes the JIRA issue to be closed](img/jira_merge_request_close.png)
+
+---
+
+Once this merge request is merged, the JIRA issue will be automatically closed
+with a link to the commit that resolved the issue.
+
+![The GitLab integration closes JIRA issue](img/jira_service_close_issue.png)
+
+---
+
+![The GitLab integration creates a comment and a link on JIRA issue.](img/jira_service_close_comment.png)
+
+## Troubleshooting
+
+If things don't work as expected that's usually because you have configured
+incorrectly the JIRA-GitLab integration.
+
+### GitLab is unable to comment on a ticket
+
+Make sure that the user you set up for GitLab to communicate with JIRA has the
+correct access permission to post comments on a ticket and to also transition
+the ticket, if you'd like GitLab to also take care of closing them.
+JIRA issue references and update comments will not work if the GitLab issue tracker is disabled.
+
+### GitLab is unable to close a ticket
+
+Make sure the `Transition ID` you set within the JIRA settings matches the one
+your project needs to close a ticket.
+
+[services-templates]: services_templates.md
+[jira-repo-old-docs]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-13-stable/doc/project_services/jira.md
diff --git a/doc/user/project/integrations/kubernetes.md b/doc/user/project/integrations/kubernetes.md
new file mode 100644
index 00000000000..73fa83d72a8
--- /dev/null
+++ b/doc/user/project/integrations/kubernetes.md
@@ -0,0 +1,71 @@
+# GitLab Kubernetes / OpenShift integration
+
+GitLab can be configured to interact with Kubernetes, or other systems using the
+Kubernetes API (such as OpenShift).
+
+Each project can be configured to connect to a different Kubernetes cluster, see
+the [configuration](#configuration) section.
+
+If you have a single cluster that you want to use for all your projects,
+you can pre-fill the settings page with a default template. To configure the
+template, see the [Services Templates](services_templates.md) document.
+
+## Configuration
+
+Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
+of your project and select the **Kubernetes** service to configure it.
+
+![Kubernetes configuration settings](img/kubernetes_configuration.png)
+
+The Kubernetes service takes the following arguments:
+
+1. Kubernetes namespace
+1. API URL
+1. Service token
+1. Custom CA bundle
+
+The API URL is the URL that GitLab uses to access the Kubernetes API. Kubernetes
+exposes several APIs - we want the "base" URL that is common to all of them,
+e.g., `https://kubernetes.example.com` rather than `https://kubernetes.example.com/api/v1`.
+
+GitLab authenticates against Kubernetes using service tokens, which are
+scoped to a particular `namespace`. If you don't have a service token yet,
+you can follow the
+[Kubernetes documentation](http://kubernetes.io/docs/user-guide/service-accounts/)
+to create one. You can also view or create service tokens in the
+[Kubernetes dashboard](http://kubernetes.io/docs/user-guide/ui/) - visit
+`Config -> Secrets`.
+
+Fill in the service token and namespace according to the values you just got.
+If the API is using a self-signed TLS certificate, you'll also need to include
+the `ca.crt` contents as the `Custom CA bundle`.
+
+## Deployment variables
+
+The Kubernetes service exposes following
+[deployment variables](../../../ci/variables/README.md#deployment-variables) in the
+GitLab CI build environment:
+
+- `KUBE_URL` - equal to the API URL
+- `KUBE_TOKEN`
+- `KUBE_NAMESPACE` - The Kubernetes namespace is auto-generated if not specified.
+ The default value is `<project_name>-<project_id>`. You can overwrite it to
+ use different one if needed, otherwise the `KUBE_NAMESPACE` variable will
+ receive the default value.
+- `KUBE_CA_PEM_FILE` - only present if a custom CA bundle was specified. Path
+ to a file containing PEM data.
+- `KUBE_CA_PEM` (deprecated)- only if a custom CA bundle was specified. Raw PEM data.
+
+## Web terminals
+
+>**NOTE:**
+Added in GitLab 8.15. You must be the project owner or have `master` permissions
+to use terminals. Support is currently limited to the first container in the
+first pod of your environment.
+
+When enabled, the Kubernetes service adds [web terminal](../../../ci/environments.md#web-terminals)
+support to your [environments](../../../ci/environments.md). This is based on the `exec` functionality found in
+Docker and Kubernetes, so you get a new shell session within your existing
+containers. To use this integration, you should deploy to Kubernetes using
+the deployment variables above, ensuring any pods you create are labelled with
+`app=$CI_ENVIRONMENT_SLUG`. GitLab will do the rest!
diff --git a/doc/user/project/integrations/mattermost.md b/doc/user/project/integrations/mattermost.md
new file mode 100644
index 00000000000..3e77823a6aa
--- /dev/null
+++ b/doc/user/project/integrations/mattermost.md
@@ -0,0 +1,45 @@
+# Mattermost Notifications Service
+
+## On Mattermost
+
+To enable Mattermost integration you must create an incoming webhook integration:
+
+1. Sign in to your Mattermost instance
+1. Visit incoming webhooks, that will be something like: https://mattermost.example/your_team_name/integrations/incoming_webhooks/add
+1. Choose a display name, description and channel, those can be overridden on GitLab
+1. Save it, copy the **Webhook URL**, we'll need this later for GitLab.
+
+There might be some cases that Incoming Webhooks are blocked by admin, ask your mattermost admin to enable
+it on https://mattermost.example/admin_console/integrations/custom.
+
+Display name override is not enabled by default, you need to ask your admin to enable it on that same section.
+
+## On GitLab
+
+After you set up Mattermost, it's time to set up GitLab.
+
+Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
+and select the **Mattermost notifications** service to configure it.
+There, you will see a checkbox with the following events that can be triggered:
+
+- Push
+- Issue
+- Confidential issue
+- Merge request
+- Note
+- Tag push
+- Pipeline
+- Wiki page
+
+Below each of these event checkboxes, you have an input field to enter
+which Mattermost channel you want to send that event message. Enter your preferred channel handle (the hash sign `#` is optional).
+
+At the end, fill in your Mattermost details:
+
+| Field | Description |
+| ----- | ----------- |
+| **Webhook** | The incoming webhook URL which you have to setup on Mattermost, it will be something like: http://mattermost.example/hooks/5xo… |
+| **Username** | Optional username which can be on messages sent to Mattermost. Fill this in if you want to change the username of the bot. |
+| **Notify only broken pipelines** | If you choose to enable the **Pipeline** event and you want to be only notified about failed pipelines. |
+
+![Mattermost configuration](img/mattermost_configuration.png)
diff --git a/doc/user/project/integrations/mattermost_slash_commands.md b/doc/user/project/integrations/mattermost_slash_commands.md
new file mode 100644
index 00000000000..488f61c77a3
--- /dev/null
+++ b/doc/user/project/integrations/mattermost_slash_commands.md
@@ -0,0 +1,164 @@
+# Mattermost slash commands
+
+> Introduced in GitLab 8.14
+
+Mattermost commands give users an extra interface to perform common operations
+from the chat environment. This allows one to, for example, create an issue as
+soon as the idea was discussed in Mattermost.
+
+## Prerequisites
+
+Mattermost 3.4 and up is required.
+
+If you have the Omnibus GitLab package installed, Mattermost is already bundled
+in it. All you have to do is configure it. Read more in the
+[Omnibus GitLab Mattermost documentation][omnimmdocs].
+
+## Automated Configuration
+
+If Mattermost is installed on the same server as GitLab, the configuration process can be
+done for you by GitLab.
+
+Go to the Mattermost Slash Command service on your project and click the 'Add to Mattermost' button.
+
+## Manual Configuration
+
+The configuration consists of two parts. First you need to enable the slash
+commands in Mattermost and then enable the service in GitLab.
+
+### Step 1. Enable custom slash commands in Mattermost
+
+This step is only required when using a source install, omnibus installs will be
+preconfigured with the right settings.
+
+The first thing to do in Mattermost is to enable custom slash commands from
+the administrator console.
+
+1. Log in with an account that has admin privileges and navigate to the system
+ console.
+
+ ![Mattermost go to console](img/mattermost_goto_console.png)
+
+ ---
+
+1. Click **Custom integrations** and set **Enable Custom Slash Commands**,
+ **Enable custom integrations to override usernames**, and **Override
+ custom integrations to override profile picture icons** to true
+
+ ![Mattermost console](img/mattermost_console_integrations.png)
+
+ ---
+
+1. Click **Save** at the bottom to save the changes.
+
+### Step 2. Open the Mattermost slash commands service in GitLab
+
+1. Open a new tab for GitLab, go to your project's
+ [Integrations page](project_services.md#accessing-the-project-services)
+ and select the **Mattermost command** service to configure it.
+ A screen will appear with all the values you need to copy in Mattermost as
+ described in the next step. Leave the window open.
+
+ >**Note:**
+ GitLab will propose some values for the Mattermost settings. The only one
+ required to copy-paste as-is is the **Request URL**, all the others are just
+ suggestions.
+
+ ![Mattermost setup instructions](img/mattermost_config_help.png)
+
+ ---
+
+1. Proceed to the next step and create a slash command in Mattermost with the
+ above values.
+
+### Step 3. Create a new custom slash command in Mattermost
+
+Now that you have enabled custom slash commands in Mattermost and opened
+the Mattermost slash commands service in GitLab, it's time to copy these values
+in a new slash command.
+
+1. Back to Mattermost, under your team page settings, you should see the
+ **Integrations** option.
+
+ ![Mattermost team integrations](img/mattermost_team_integrations.png)
+
+ ---
+
+1. Go to the **Slash Commands** integration and add a new one by clicking the
+ **Add Slash Command** button.
+
+ ![Mattermost add command](img/mattermost_add_slash_command.png)
+
+ ---
+
+1. Fill in the options for the custom command as described in
+ [step 2](#step-2-open-the-mattermost-slash-commands-service-in-gitlab).
+
+ >**Note:**
+ If you plan on connecting multiple projects, pick a slash command trigger
+ word that relates to your projects such as `/gitlab-project-name` or even
+ just `/project-name`. Only use `/gitlab` if you will only connect a single
+ project to your Mattermost team.
+
+ ![Mattermost add command configuration](img/mattermost_slash_command_configuration.png)
+
+1. After you setup all the values, copy the token (we will use it below) and
+ click **Done**.
+
+ ![Mattermost slash command token](img/mattermost_slash_command_token.png)
+
+### Step 4. Copy the Mattermost token into the Mattermost slash command service
+
+1. In GitLab, paste the Mattermost token you copied in the previous step and
+ check the **Active** checkbox.
+
+ ![Mattermost copy token to GitLab](img/mattermost_gitlab_token.png)
+
+1. Click **Save changes** for the changes to take effect.
+
+---
+
+You are now set to start using slash commands in Mattermost that talk to the
+GitLab project you configured.
+
+## Authorizing Mattermost to interact with GitLab
+
+The first time a user will interact with the newly created slash commands,
+Mattermost will trigger an authorization process.
+
+![Mattermost bot authorize](img/mattermost_bot_auth.png)
+
+This will connect your Mattermost user with your GitLab user. You can
+see all authorized chat accounts in your profile's page under **Chat**.
+
+When the authorization process is complete, you can start interacting with
+GitLab using the Mattermost commands.
+
+## Available slash commands
+
+The available slash commands are:
+
+| Command | Description | Example |
+| ------- | ----------- | ------- |
+| <kbd>/&lt;trigger&gt; issue new &lt;title&gt; <kbd>⇧ Shift</kbd>+<kbd>↵ Enter</kbd> &lt;description&gt;</kbd> | Create a new issue in the project that `<trigger>` is tied to. `<description>` is optional. | <samp>/gitlab issue new We need to change the homepage</samp> |
+| <kbd>/&lt;trigger&gt; issue show &lt;issue-number&gt;</kbd> | Show the issue with ID `<issue-number>` from the project that `<trigger>` is tied to. | <samp>/gitlab issue show 42</samp> |
+| <kbd>/&lt;trigger&gt; deploy &lt;environment&gt; to &lt;environment&gt;</kbd> | Start the CI job that deploys from one environment to another, for example `staging` to `production`. CI/CD must be [properly configured][ciyaml]. | <samp>/gitlab deploy staging to production</samp> |
+
+To see a list of available commands to interact with GitLab, type the
+trigger word followed by <kbd>help</kbd>. Example: <samp>/gitlab help</samp>
+
+![Mattermost bot available commands](img/mattermost_bot_available_commands.png)
+
+## Permissions
+
+The permissions to run the [available commands](#available-slash-commands) derive from
+the [permissions you have on the project](../../permissions.md#project).
+
+## Further reading
+
+- [Mattermost slash commands documentation][mmslashdocs]
+- [Omnibus GitLab Mattermost][omnimmdocs]
+
+[omnimmdocs]: https://docs.gitlab.com/omnibus/gitlab-mattermost/
+[mmslashdocs]: https://docs.mattermost.com/developer/slash-commands.html
+[ciyaml]: ../../../ci/yaml/README.md
diff --git a/doc/user/project/integrations/microsoft_teams.md b/doc/user/project/integrations/microsoft_teams.md
new file mode 100644
index 00000000000..eaad2d5138a
--- /dev/null
+++ b/doc/user/project/integrations/microsoft_teams.md
@@ -0,0 +1,33 @@
+# Microsoft Teams service
+
+## On Microsoft Teams
+
+To enable Microsoft Teams integration you must create an incoming webhook integration on Microsoft Teams by following the steps described in this [document](https://msdn.microsoft.com/en-us/microsoft-teams/connectors).
+
+## On GitLab
+
+After you set up Microsoft Teams, it's time to set up GitLab.
+
+Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
+and select the **Microsoft Teams Notification** service to configure it.
+There, you will see a checkbox with the following events that can be triggered:
+
+- Push
+- Issue
+- Confidential issue
+- Merge request
+- Note
+- Tag push
+- Pipeline
+- Wiki page
+
+At the end fill in your Microsoft Teams details:
+
+| Field | Description |
+| ----- | ----------- |
+| **Webhook** | The incoming webhook URL which you have to setup on Microsoft Teams. |
+| **Notify only broken pipelines** | If you choose to enable the **Pipeline** event and you want to be only notified about failed pipelines. |
+
+After you are all done, click **Save changes** for the changes to take effect.
+
+![Microsoft Teams configuration](img/microsoft_teams_configuration.png)
diff --git a/doc/user/project/integrations/mock_ci.md b/doc/user/project/integrations/mock_ci.md
new file mode 100644
index 00000000000..6aefe5dbded
--- /dev/null
+++ b/doc/user/project/integrations/mock_ci.md
@@ -0,0 +1,13 @@
+# Mock CI Service
+
+**NB: This service is only listed if you are in a development environment!**
+
+To setup the mock CI service server, respond to the following endpoints
+
+- `commit_status`: `#{project.namespace.path}/#{project.path}/status/#{sha}.json`
+ - Have your service return `200 { status: ['failed'|'canceled'|'running'|'pending'|'success'|'success_with_warnings'|'skipped'|'not_found'] }`
+ - If the service returns a 404, it is interpreted as `pending`
+- `build_page`: `#{project.namespace.path}/#{project.path}/status/#{sha}`
+ - Just where the build is linked to, doesn't matter if implemented
+
+For an example of a mock CI server, see [`gitlab-org/gitlab-mock-ci-service`](https://gitlab.com/gitlab-org/gitlab-mock-ci-service)
diff --git a/doc/user/project/integrations/project_services.md b/doc/user/project/integrations/project_services.md
new file mode 100644
index 00000000000..51989ccaaea
--- /dev/null
+++ b/doc/user/project/integrations/project_services.md
@@ -0,0 +1,73 @@
+# Project services
+
+Project services allow you to integrate GitLab with other applications. They
+are a bit like plugins in that they allow a lot of freedom in adding
+functionality to GitLab.
+
+## Accessing the project services
+
+You can find the available services under your project's
+**Settings ➔ Integrations** page.
+
+There are more than 20 services to integrate with. Click on the one that you
+want to configure.
+
+ ![Project services list](img/project_services.png)
+
+Below, you will find a list of the currently supported ones accompanied with
+comprehensive documentation.
+
+## Services
+
+Click on the service links to see further configuration instructions and details.
+
+| Service | Description |
+| ------- | ----------- |
+| Asana | Asana - Teamwork without email |
+| Assembla | Project Management Software (Source Commits Endpoint) |
+| [Atlassian Bamboo CI](bamboo.md) | A continuous integration and build server |
+| Buildkite | Continuous integration and deployments |
+| [Bugzilla](bugzilla.md) | Bugzilla issue tracker |
+| Campfire | Simple web-based real-time group chat |
+| Custom Issue Tracker | Custom issue tracker |
+| Drone CI | Continuous Integration platform built on Docker, written in Go |
+| [Emails on push](emails_on_push.md) | Email the commits and diff of each push to a list of recipients |
+| External Wiki | Replaces the link to the internal wiki with a link to an external wiki |
+| Flowdock | Flowdock is a collaboration web app for technical teams |
+| Gemnasium | Gemnasium monitors your project dependencies and alerts you about updates and security vulnerabilities |
+| [HipChat](hipchat.md) | Private group chat and IM |
+| [Irker (IRC gateway)](irker.md) | Send IRC messages, on update, to a list of recipients through an Irker gateway |
+| [JIRA](jira.md) | JIRA issue tracker |
+| JetBrains TeamCity CI | A continuous integration and build server |
+| [Kubernetes](kubernetes.md) | A containerized deployment service |
+| [Mattermost slash commands](mattermost_slash_commands.md) | Mattermost chat and ChatOps slash commands |
+| [Mattermost Notifications](mattermost.md) | Receive event notifications in Mattermost |
+| [Microsoft teams](microsoft_teams.md) | Receive notifications for actions that happen on GitLab into a room on Microsoft Teams using Office 365 Connectors |
+| Pipelines emails | Email the pipeline status to a list of recipients |
+| [Slack Notifications](slack.md) | Send GitLab events (e.g. issue created) to Slack as notifications |
+| [Slack slash commands](slack_slash_commands.md) | Use slash commands in Slack to control GitLab |
+| PivotalTracker | Project Management Software (Source Commits Endpoint) |
+| [Prometheus](prometheus.md) | Monitor the performance of your deployed apps |
+| Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop |
+| [Redmine](redmine.md) | Redmine issue tracker |
+
+## Services templates
+
+Services templates is a way to set some predefined values in the Service of
+your liking which will then be pre-filled on each project's Service.
+
+Read more about [Services templates in this document](services_templates.md).
+
+## Contributing to project services
+
+Because GitLab is open source we can ship with the code and tests for all
+plugins. This allows the community to keep the plugins up to date so that they
+always work in newer GitLab versions.
+
+For an overview of what projects services are available, please see the
+[project_services source directory][projects-code].
+
+Contributions are welcome!
+
+[projects-code]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/models/project_services
+[permissions]: ../../permissions.md
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
new file mode 100644
index 00000000000..86ceb14b965
--- /dev/null
+++ b/doc/user/project/integrations/prometheus.md
@@ -0,0 +1,208 @@
+# Prometheus integration
+
+> [Introduced][ce-8935] in GitLab 9.0.
+
+GitLab offers powerful integration with [Prometheus] for monitoring your apps.
+Metrics are retrieved from the configured Prometheus server, and then displayed
+within the GitLab interface.
+
+Each project can be configured with its own specific Prometheus server, see the
+[configuration](#configuration) section for more details. If you have a single
+Prometheus server which monitors all of your infrastructure, you can pre-fill
+the settings page with a default template. To configure the template, see the
+[Services templates](services_templates.md) document.
+
+## Requirements
+
+Integration with Prometheus requires the following:
+
+1. GitLab 9.0 or higher
+1. The [Kubernetes integration must be enabled][kube] on your project
+1. Your app must be deployed on [Kubernetes][]
+1. Prometheus must be configured to collect Kubernetes metrics
+1. Each metric must be have a label to indicate the environment
+1. GitLab must have network connectivity to the Prometheus sever
+
+There are a few steps necessary to set up integration between Prometheus and
+GitLab.
+
+## Configuring Prometheus to collect Kubernetes metrics
+
+In order for Prometheus to collect Kubernetes metrics, you first must have a
+Prometheus server up and running. You have two options here:
+
+- If you installed Omnibus GitLab inside of Kubernetes, you can simply use the
+ [bundled version of Prometheus][promgldocs]. In that case, follow the info in the
+ [Omnibus GitLab section](#configuring-omnibus-gitlab-prometheus-to-monitor-kubernetes)
+ below.
+- If you are using GitLab.com or installed GitLab outside of Kubernetes, you
+ will likely need to run a Prometheus server within the Kubernetes cluster.
+ Once installed, the easiest way to monitor Kubernetes is to simply use
+ Prometheus' support for [Kubernetes Service Discovery][prometheus-k8s-sd].
+ In that case, follow the instructions on
+ [configuring your own Prometheus server within Kubernetes](#configuring-your-own-prometheus-server-within-kubernetes).
+
+### Configuring Omnibus GitLab Prometheus to monitor Kubernetes
+
+With Omnibus GitLab running inside of Kubernetes, you can leverage the bundled
+version of Prometheus to collect the required metrics.
+
+1. Read how to configure the bundled Prometheus server in the
+ [Administration guide][gitlab-prometheus-k8s-monitor].
+1. Now that Prometheus is configured, proceed on
+ [configuring the Prometheus project service in GitLab](#configuration-in-gitlab).
+
+### Configuring your own Prometheus server within Kubernetes
+
+Setting up and configuring Prometheus within Kubernetes is quick and painless.
+The Prometheus project provides an [official Docker image][prometheus-docker-image]
+which we can use as a starting point.
+
+To get started quickly, we have provided a [sample YML file][prometheus-yml]
+that can be used as a template. This file will create a `prometheus` **Namespace**,
+**Service**, **Deployment**, and **ConfigMap** in Kubernetes. You can upload
+this file to the Kubernetes dashboard using **+ Create** at the top right.
+
+![Deploy Prometheus](img/prometheus_yaml_deploy.png)
+
+Or use `kubectl`:
+
+```bash
+kubectl apply -f path/to/prometheus.yml
+```
+
+Once deployed, you should see the Prometheus service, deployment, and
+pod start within the `prometheus` namespace. The server will begin to collect
+metrics from each Kubernetes Node in the cluster, based on the configuration
+provided in the template.
+
+Since GitLab is not running within Kubernetes, the template provides external
+network access via a `NodePort` running on `30090`. This method allows access
+to be controlled using provider firewall rules, like within Google Compute Engine.
+
+Since a `NodePort` does not automatically have firewall rules created for it,
+one will need to be created manually to allow access. In GCP/GKE, you will want
+to confirm the Node that the Prometheus pod is running on. This can be done
+either by looking at the Pod in the Kubernetes dashboard, or by running:
+
+```bash
+kubectl describe pods -n prometheus
+```
+
+Next on GKE, we need to get the `tag` of the Node or VM Instance, so we can
+create an accurate firewall rule. The easiest way to do this is to go into the
+Google Cloud Platform Compute console and select the VM instance that matches
+the name of the Node gathered from the step above. In this case, the node tag
+needed is `gke-prometheus-demo-5d5ada10-node`. Also make a note of the
+**External IP**, which will be the IP address the Prometheus server is reachable
+on.
+
+![GCP Node Detail](img/prometheus_gcp_node_name.png)
+
+Armed with the proper Node tag, the firewall rule can now be created
+specifically for this node. To create the firewall rule, open the Google Cloud
+Platform Networking console, and select **Firewall Rules**.
+
+Create a new rule:
+
+- Specify the source IP range to match your desired access list, which should
+ include your GitLab server. A sample of GitLab.com's IP address range is
+ available [in this issue][gitlab.com-ip-range], but note that GitLab.com's IPs
+ are subject to change without prior notification.
+- Allowed protocol and port should be `tcp:30090`.
+- The target tags should match the Node tag identified earlier in this step.
+
+![GCP Firewall Rule](img/prometheus_gcp_firewall_rule.png)
+
+---
+
+Now that Prometheus is configured, proceed to
+[configure the Prometheus project service in GitLab](##configuration-in-gitlab).
+
+## Configuration in GitLab
+
+The actual configuration of Prometheus integration within GitLab is very simple.
+All you will need is the DNS or IP address of the Prometheus server you'd like
+to integrate with.
+
+1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
+1. Click the **Prometheus** service
+1. Provide the base URL of the your server, for example `http://prometheus.example.com/`.
+ The **Test Settings** button can be used to confirm connectivity from GitLab
+ to the Prometheus server.
+
+![Configure Prometheus Service](img/prometheus_service_configuration.png)
+
+## Metrics and Labels
+
+GitLab retrieves performance data from two metrics, `container_cpu_usage_seconds_total`
+and `container_memory_usage_bytes`. These metrics are collected from the
+Kubernetes pods via Prometheus, and report CPU and Memory utilization of each
+container or Pod running in the cluster.
+
+In order to isolate and only display relevant metrics for a given environment
+however, GitLab needs a method to detect which pods are associated. To do that,
+GitLab will specifically request metrics that have an `environment` tag that
+matches the [$CI_ENVIRONMENT_SLUG][ci-environment-slug].
+
+If you are using [GitLab Auto-Deploy][autodeploy] and one of the methods of
+configuring Prometheus above, the `environment` will be automatically added.
+
+### GitLab Prometheus queries
+
+The queries utilized by GitLab are shown in the following table.
+
+| Metric | Query |
+| ------ | ----- |
+| Average Memory (MB) | `(sum(container_memory_usage_bytes{container_name!="POD",environment="$CI_ENVIRONMENT_SLUG"}) / count(container_memory_usage_bytes{container_name!="POD",environment="$CI_ENVIRONMENT_SLUG"})) /1024/1024` |
+| Average CPU Utilization (%) | `sum(rate(container_cpu_usage_seconds_total{container_name!="POD",environment="$CI_ENVIRONMENT_SLUG"}[2m])) / count(container_cpu_usage_seconds_total{container_name!="POD",environment="$CI_ENVIRONMENT_SLUG"}) * 100` |
+
+## Monitoring CI/CD Environments
+
+Once configured, GitLab will attempt to retrieve performance metrics for any
+environment which has had a successful deployment.
+
+[Learn more about monitoring environments.](../../../ci/environments.md#monitoring-environments)
+
+## Determining the performance impact of a merge
+
+> [Introduced][ce-10408] in GitLab 9.2.
+> GitLab 9.3 added the [numeric comparison](https://gitlab.com/gitlab-org/gitlab-ce/issues/27439) of the 30 minute averages.
+
+Developers can view the performance impact of their changes within the merge
+request workflow. When a source branch has been deployed to an environment, a sparkline and numeric comparison of the average memory consumption will appear. On the sparkline, a dot
+indicates when the current changes were deployed, with up to 30 minutes of
+performance data displayed before and after. The comparison shows the difference between the 30 minute average before and after the deployment. This information is updated after
+each commit has been deployed.
+
+Once merged and the target branch has been redeployed, the metrics will switch
+to show the new environments this revision has been deployed to.
+
+Performance data will be available for the duration it is persisted on the
+Prometheus server.
+
+![Merge Request with Performance Impact](img/merge_request_performance.png)
+
+## Troubleshooting
+
+If the "Attempting to load performance data" screen continues to appear, it could be due to:
+
+- No successful deployments have occurred to this environment.
+- Prometheus does not have performance data for this environment, or the metrics
+ are not labeled correctly. To test this, connect to the Prometheus server and
+ [run a query](#gitlab-prometheus-queries), replacing `$CI_ENVIRONMENT_SLUG`
+ with the name of your environment.
+
+[autodeploy]: ../../../ci/autodeploy/index.md
+[kubernetes]: https://kubernetes.io
+[kube]: ./kubernetes.md
+[prometheus-k8s-sd]: https://prometheus.io/docs/operating/configuration/#<kubernetes_sd_config>
+[prometheus]: https://prometheus.io
+[gitlab-prometheus-k8s-monitor]: ../../../administration/monitoring/prometheus/index.md#configuring-prometheus-to-monitor-kubernetes
+[prometheus-docker-image]: https://hub.docker.com/r/prom/prometheus/
+[prometheus-yml]:samples/prometheus.yml
+[gitlab.com-ip-range]: https://gitlab.com/gitlab-com/infrastructure/issues/434
+[ci-environment-slug]: https://docs.gitlab.com/ce/ci/variables/#predefined-variables-environment-variables
+[ce-8935]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8935
+[ce-10408]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10408
+[promgldocs]: ../../../administration/monitoring/prometheus/index.md
diff --git a/doc/user/project/integrations/redmine.md b/doc/user/project/integrations/redmine.md
new file mode 100644
index 00000000000..89c0312d3c2
--- /dev/null
+++ b/doc/user/project/integrations/redmine.md
@@ -0,0 +1,23 @@
+# Redmine Service
+
+To enable the Redmine integration in a project, navigate to the
+[Integrations page](project_services.md#accessing-the-project-services), click
+the **Redmine** service, and fill in the required details on the page as described
+in the table below.
+
+| Field | Description |
+| ----- | ----------- |
+| `description` | A name for the issue tracker (to differentiate between instances, for example) |
+| `project_url` | The URL to the project in Redmine which is being linked to this GitLab project |
+| `issues_url` | The URL to the issue in Redmine project that is linked to this GitLab project. Note that the `issues_url` requires `:id` in the URL. This ID is used by GitLab as a placeholder to replace the issue number. |
+| `new_issue_url` | This is the URL to create a new issue in Redmine for the project linked to this GitLab project |
+
+Once you have configured and enabled Redmine:
+
+- the **Issues** link on the GitLab project pages takes you to the appropriate
+ Redmine issue index
+- clicking **New issue** on the project dashboard creates a new Redmine issue
+
+As an example, below is a configuration for a project named gitlab-ci.
+
+![Redmine configuration](img/redmine_configuration.png)
diff --git a/doc/user/project/integrations/samples/prometheus.yml b/doc/user/project/integrations/samples/prometheus.yml
new file mode 100644
index 00000000000..01bbcaffe1e
--- /dev/null
+++ b/doc/user/project/integrations/samples/prometheus.yml
@@ -0,0 +1,69 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: prometheus
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: prometheus
+ namespace: prometheus
+data:
+ prometheus.yml: |-
+ scrape_configs:
+ - job_name: 'kubernetes-nodes'
+ scheme: https
+ tls_config:
+ ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
+ insecure_skip_verify: true
+ bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
+ kubernetes_sd_configs:
+ - role: node
+ metric_relabel_configs:
+ - source_labels: [pod_name]
+ target_label: environment
+ regex: (.+)-.+-.+
+ replacement: $1
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: prometheus
+ namespace: prometheus
+spec:
+ selector:
+ app: prometheus
+ ports:
+ - name: prometheus
+ protocol: TCP
+ port: 9090
+ nodePort: 30090
+ type: NodePort
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: prometheus
+ namespace: prometheus
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: prometheus
+ spec:
+ containers:
+ - name: prometheus
+ image: prom/prometheus:latest
+ args:
+ - '-config.file=/prometheus-data/prometheus.yml'
+ ports:
+ - name: prometheus
+ containerPort: 9090
+ volumeMounts:
+ - name: data-volume
+ mountPath: /prometheus-data
+ volumes:
+ - name: data-volume
+ configMap:
+ name: prometheus
diff --git a/doc/user/project/integrations/services_templates.md b/doc/user/project/integrations/services_templates.md
new file mode 100644
index 00000000000..5b04d7d88b8
--- /dev/null
+++ b/doc/user/project/integrations/services_templates.md
@@ -0,0 +1,26 @@
+# Services templates
+
+A GitLab administrator can add a service template that sets a default for each
+project. After a service template is enabled, it will be applied to new
+projects only and its details will be pre-filled on the project's Service page.
+
+## Enable a service template
+
+In GitLab's Admin area, navigate to **Service Templates** and choose the
+service template you wish to create.
+
+## Services for external issue trackers
+
+In the image below you can see how a service template for Redmine would look
+like.
+
+![Redmine service template](img/services_templates_redmine_example.png)
+
+---
+
+For each project, you will still need to configure the issue tracking
+URLs by replacing `:issues_tracker_id` in the above screenshot with the ID used
+by your external issue tracker. Prior to GitLab v7.8, this ID was configured in
+the project settings, and GitLab would automatically update the URL configured
+in `gitlab.yml`. This behavior is now deprecated and all issue tracker URLs
+must be configured directly within the project's **Integrations** settings.
diff --git a/doc/user/project/integrations/slack.md b/doc/user/project/integrations/slack.md
new file mode 100644
index 00000000000..af4ca35a215
--- /dev/null
+++ b/doc/user/project/integrations/slack.md
@@ -0,0 +1,26 @@
+# Slack Notifications Service
+
+The Slack Notifications Service allows your GitLab project to send events (e.g. issue created) to your existing Slack team as notifications. This requires configurations in both Slack and GitLab.
+
+> Note: You can also use Slack slash commands to control GitLab inside Slack. This is the separately configured [Slack slash commands](slack_slash_commands.md).
+
+## Slack Configuration
+
+1. Sign in to your Slack team and [start a new Incoming WebHooks configuration](https://my.slack.com/services/new/incoming-webhook/).
+1. Select the Slack channel where notifications will be sent to by default. Click the **Add Incoming WebHooks integration** button to add the configuration.
+1. Copy the **Webhook URL**, which we'll use later in the GitLab configuration.
+
+## GitLab Configuration
+
+1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings, i.e. **Project > Settings > Integrations**.
+1. Select the **Slack notifications** project service to configure it.
+1. Check the **Active** checkbox to turn on the service.
+1. Check the checkboxes corresponding to the GitLab events you want to send to Slack as a notification.
+1. For each event, optionally enter the Slack channel where you want to send the event. (Do _not_ include the `#` symbol.) If left empty, the event will be sent to the default channel that you configured in the Slack Configuration step.
+1. Paste the **Webhook URL** that you copied from the Slack Configuration step.
+1. Optionally customize the Slack bot username that will be sending the notifications.
+1. Configure the remaining options and click `Save changes`.
+
+Your Slack team will now start receiving GitLab event notifications as configured.
+
+![Slack configuration](img/slack_configuration.png) \ No newline at end of file
diff --git a/doc/user/project/integrations/slack_slash_commands.md b/doc/user/project/integrations/slack_slash_commands.md
new file mode 100644
index 00000000000..c267da69bb3
--- /dev/null
+++ b/doc/user/project/integrations/slack_slash_commands.md
@@ -0,0 +1,23 @@
+# Slack slash commands
+
+> Introduced in GitLab 8.15
+
+Slack slash commands allow you to control GitLab and view content right inside Slack, without having to leave it. This requires configurations in both Slack and GitLab.
+
+> Note: GitLab can also send events (e.g. issue created) to Slack as notifications. This is the separately configured [Slack Notifications Service](slack.md).
+
+## Configuration
+
+1. Slack slash commands are scoped to a project. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings, i.e. **Project > Settings > Integrations**.
+1. Select the **Slack slash commands** project service to configure it. This page contains required information to complete the configuration in Slack. Leave this browser tab open.
+1. Open a new browser tab and sign in to your Slack team. [Start a new Slash Commands integration](https://my.slack.com/services/new/slash-commands).
+1. Enter a trigger term. We suggest you use the project name. Click **Add Slash Command Integration**.
+1. Complete the rest of the fields in the Slack configuration page using information from the GitLab browser tab. In particular, the URL needs to be copied and pasted. Click **Save Integration** to complete the configuration in Slack.
+1. While still on the Slack configuration page, copy the **token**. Go back to the GitLab browser tab and paste in the **token**.
+1. Check the **Active** checkbox and click **Save changes** to complete the configuration in GitLab.
+
+![Slack setup instructions](img/slack_setup.png)
+
+## Usage
+
+You can now use the [Slack slash commands](../../../integration/slash_commands.md).
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
new file mode 100644
index 00000000000..023c6932e41
--- /dev/null
+++ b/doc/user/project/integrations/webhooks.md
@@ -0,0 +1,1066 @@
+# Webhooks
+
+>**Note:**
+Starting from GitLab 8.5:
+- the `repository` key is deprecated in favor of the `project` key
+- the `project.ssh_url` key is deprecated in favor of the `project.git_ssh_url` key
+- the `project.http_url` key is deprecated in favor of the `project.git_http_url` key
+
+Project webhooks allow you to trigger a URL if for example new code is pushed or
+a new issue is created. You can configure webhooks to listen for specific events
+like pushes, issues or merge requests. GitLab will send a POST request with data
+to the webhook URL.
+
+Webhooks can be used to update an external issue tracker, trigger CI jobs,
+update a backup mirror, or even deploy to your production server.
+
+Navigate to the webhooks page by going to your project's
+**Settings ➔ Integrations**.
+
+## Webhook endpoint tips
+
+If you are writing your own endpoint (web server) that will receive
+GitLab webhooks keep in mind the following things:
+
+- Your endpoint should send its HTTP response as fast as possible. If
+ you wait too long, GitLab may decide the hook failed and retry it.
+- Your endpoint should ALWAYS return a valid HTTP response. If you do
+ not do this then GitLab will think the hook failed and retry it.
+ Most HTTP libraries take care of this for you automatically but if
+ you are writing a low-level hook this is important to remember.
+- GitLab ignores the HTTP status code returned by your endpoint.
+
+## Secret token
+
+If you specify a secret token, it will be sent with the hook request in the
+`X-Gitlab-Token` HTTP header. Your webhook endpoint can check that to verify
+that the request is legitimate.
+
+## SSL verification
+
+By default, the SSL certificate of the webhook endpoint is verified based on
+an internal list of Certificate Authorities, which means the certificate cannot
+be self-signed.
+
+You can turn this off in the webhook settings in your GitLab projects.
+
+![SSL Verification](img/webhooks_ssl.png)
+
+## Events
+
+Below are described the supported events.
+
+### Push events
+
+Triggered when you push to the repository except when pushing tags.
+
+**Request header**:
+
+```
+X-Gitlab-Event: Push Hook
+```
+
+**Request body:**
+
+```json
+{
+ "object_kind": "push",
+ "before": "95790bf891e76fee5e1747ab589903a6a1f80f22",
+ "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
+ "ref": "refs/heads/master",
+ "checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
+ "user_id": 4,
+ "user_name": "John Smith",
+ "user_username": "jsmith",
+ "user_email": "john@example.com",
+ "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
+ "project_id": 15,
+ "project":{
+ "name":"Diaspora",
+ "description":"",
+ "web_url":"http://example.com/mike/diaspora",
+ "avatar_url":null,
+ "git_ssh_url":"git@example.com:mike/diaspora.git",
+ "git_http_url":"http://example.com/mike/diaspora.git",
+ "namespace":"Mike",
+ "visibility_level":0,
+ "path_with_namespace":"mike/diaspora",
+ "default_branch":"master",
+ "homepage":"http://example.com/mike/diaspora",
+ "url":"git@example.com:mike/diaspora.git",
+ "ssh_url":"git@example.com:mike/diaspora.git",
+ "http_url":"http://example.com/mike/diaspora.git"
+ },
+ "repository":{
+ "name": "Diaspora",
+ "url": "git@example.com:mike/diaspora.git",
+ "description": "",
+ "homepage": "http://example.com/mike/diaspora",
+ "git_http_url":"http://example.com/mike/diaspora.git",
+ "git_ssh_url":"git@example.com:mike/diaspora.git",
+ "visibility_level":0
+ },
+ "commits": [
+ {
+ "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
+ "message": "Update Catalan translation to e38cb41.",
+ "timestamp": "2011-12-12T14:27:31+02:00",
+ "url": "http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
+ "author": {
+ "name": "Jordi Mallach",
+ "email": "jordi@softcatala.org"
+ },
+ "added": ["CHANGELOG"],
+ "modified": ["app/controller/application.rb"],
+ "removed": []
+ },
+ {
+ "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
+ "message": "fixed readme",
+ "timestamp": "2012-01-03T23:36:29+02:00",
+ "url": "http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
+ "author": {
+ "name": "GitLab dev user",
+ "email": "gitlabdev@dv6700.(none)"
+ },
+ "added": ["CHANGELOG"],
+ "modified": ["app/controller/application.rb"],
+ "removed": []
+ }
+ ],
+ "total_commits_count": 4
+}
+```
+
+### Tag events
+
+Triggered when you create (or delete) tags to the repository.
+
+**Request header**:
+
+```
+X-Gitlab-Event: Tag Push Hook
+```
+
+**Request body:**
+
+```json
+{
+ "object_kind": "tag_push",
+ "before": "0000000000000000000000000000000000000000",
+ "after": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7",
+ "ref": "refs/tags/v1.0.0",
+ "checkout_sha": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7",
+ "user_id": 1,
+ "user_name": "John Smith",
+ "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
+ "project_id": 1,
+ "project":{
+ "name":"Example",
+ "description":"",
+ "web_url":"http://example.com/jsmith/example",
+ "avatar_url":null,
+ "git_ssh_url":"git@example.com:jsmith/example.git",
+ "git_http_url":"http://example.com/jsmith/example.git",
+ "namespace":"Jsmith",
+ "visibility_level":0,
+ "path_with_namespace":"jsmith/example",
+ "default_branch":"master",
+ "homepage":"http://example.com/jsmith/example",
+ "url":"git@example.com:jsmith/example.git",
+ "ssh_url":"git@example.com:jsmith/example.git",
+ "http_url":"http://example.com/jsmith/example.git"
+ },
+ "repository":{
+ "name": "Example",
+ "url": "ssh://git@example.com/jsmith/example.git",
+ "description": "",
+ "homepage": "http://example.com/jsmith/example",
+ "git_http_url":"http://example.com/jsmith/example.git",
+ "git_ssh_url":"git@example.com:jsmith/example.git",
+ "visibility_level":0
+ },
+ "commits": [],
+ "total_commits_count": 0
+}
+```
+
+### Issues events
+
+Triggered when a new issue is created or an existing issue was updated/closed/reopened.
+
+**Request header**:
+
+```
+X-Gitlab-Event: Issue Hook
+```
+
+**Request body:**
+
+```json
+{
+ "object_kind": "issue",
+ "user": {
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ },
+ "project":{
+ "name":"Gitlab Test",
+ "description":"Aut reprehenderit ut est.",
+ "web_url":"http://example.com/gitlabhq/gitlab-test",
+ "avatar_url":null,
+ "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git",
+ "git_http_url":"http://example.com/gitlabhq/gitlab-test.git",
+ "namespace":"GitlabHQ",
+ "visibility_level":20,
+ "path_with_namespace":"gitlabhq/gitlab-test",
+ "default_branch":"master",
+ "homepage":"http://example.com/gitlabhq/gitlab-test",
+ "url":"http://example.com/gitlabhq/gitlab-test.git",
+ "ssh_url":"git@example.com:gitlabhq/gitlab-test.git",
+ "http_url":"http://example.com/gitlabhq/gitlab-test.git"
+ },
+ "repository":{
+ "name": "Gitlab Test",
+ "url": "http://example.com/gitlabhq/gitlab-test.git",
+ "description": "Aut reprehenderit ut est.",
+ "homepage": "http://example.com/gitlabhq/gitlab-test"
+ },
+ "object_attributes": {
+ "id": 301,
+ "title": "New API: create/update/delete file",
+ "assignee_ids": [51],
+ "assignee_id": 51,
+ "author_id": 51,
+ "project_id": 14,
+ "created_at": "2013-12-03T17:15:43Z",
+ "updated_at": "2013-12-03T17:15:43Z",
+ "position": 0,
+ "branch_name": null,
+ "description": "Create new API for manipulations with repository",
+ "milestone_id": null,
+ "state": "opened",
+ "iid": 23,
+ "url": "http://example.com/diaspora/issues/23",
+ "action": "open"
+ },
+ "assignees": [{
+ "name": "User1",
+ "username": "user1",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ }],
+ "assignee": {
+ "name": "User1",
+ "username": "user1",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ },
+ "labels": [{
+ "id": 206,
+ "title": "API",
+ "color": "#ffffff",
+ "project_id": 14,
+ "created_at": "2013-12-03T17:15:43Z",
+ "updated_at": "2013-12-03T17:15:43Z",
+ "template": false,
+ "description": "API related issues",
+ "type": "ProjectLabel",
+ "group_id": 41
+ }]
+}
+```
+
+**Note**: `assignee` and `assignee_id` keys are deprecated and now show the first assignee only.
+
+### Comment events
+
+Triggered when a new comment is made on commits, merge requests, issues, and code snippets.
+The note data will be stored in `object_attributes` (e.g. `note`, `noteable_type`). The
+payload will also include information about the target of the comment. For example,
+a comment on a issue will include the specific issue information under the `issue` key.
+Valid target types:
+
+1. `commit`
+2. `merge_request`
+3. `issue`
+4. `snippet`
+
+#### Comment on commit
+
+**Request header**:
+
+```
+X-Gitlab-Event: Note Hook
+```
+
+**Request body:**
+
+```json
+{
+ "object_kind": "note",
+ "user": {
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ },
+ "project_id": 5,
+ "project":{
+ "name":"Gitlab Test",
+ "description":"Aut reprehenderit ut est.",
+ "web_url":"http://example.com/gitlabhq/gitlab-test",
+ "avatar_url":null,
+ "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git",
+ "git_http_url":"http://example.com/gitlabhq/gitlab-test.git",
+ "namespace":"GitlabHQ",
+ "visibility_level":20,
+ "path_with_namespace":"gitlabhq/gitlab-test",
+ "default_branch":"master",
+ "homepage":"http://example.com/gitlabhq/gitlab-test",
+ "url":"http://example.com/gitlabhq/gitlab-test.git",
+ "ssh_url":"git@example.com:gitlabhq/gitlab-test.git",
+ "http_url":"http://example.com/gitlabhq/gitlab-test.git"
+ },
+ "repository":{
+ "name": "Gitlab Test",
+ "url": "http://example.com/gitlab-org/gitlab-test.git",
+ "description": "Aut reprehenderit ut est.",
+ "homepage": "http://example.com/gitlab-org/gitlab-test"
+ },
+ "object_attributes": {
+ "id": 1243,
+ "note": "This is a commit comment. How does this work?",
+ "noteable_type": "Commit",
+ "author_id": 1,
+ "created_at": "2015-05-17 18:08:09 UTC",
+ "updated_at": "2015-05-17 18:08:09 UTC",
+ "project_id": 5,
+ "attachment":null,
+ "line_code": "bec9703f7a456cd2b4ab5fb3220ae016e3e394e3_0_1",
+ "commit_id": "cfe32cf61b73a0d5e9f13e774abde7ff789b1660",
+ "noteable_id": null,
+ "system": false,
+ "st_diff": {
+ "diff": "--- /dev/null\n+++ b/six\n@@ -0,0 +1 @@\n+Subproject commit 409f37c4f05865e4fb208c771485f211a22c4c2d\n",
+ "new_path": "six",
+ "old_path": "six",
+ "a_mode": "0",
+ "b_mode": "160000",
+ "new_file": true,
+ "renamed_file": false,
+ "deleted_file": false
+ },
+ "url": "http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660#note_1243"
+ },
+ "commit": {
+ "id": "cfe32cf61b73a0d5e9f13e774abde7ff789b1660",
+ "message": "Add submodule\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n",
+ "timestamp": "2014-02-27T10:06:20+02:00",
+ "url": "http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660",
+ "author": {
+ "name": "Dmitriy Zaporozhets",
+ "email": "dmitriy.zaporozhets@gmail.com"
+ }
+ }
+}
+```
+
+#### Comment on merge request
+
+**Request header**:
+
+```
+X-Gitlab-Event: Note Hook
+```
+
+**Request body:**
+
+```json
+{
+ "object_kind": "note",
+ "user": {
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ },
+ "project_id": 5,
+ "project":{
+ "name":"Gitlab Test",
+ "description":"Aut reprehenderit ut est.",
+ "web_url":"http://example.com/gitlab-org/gitlab-test",
+ "avatar_url":null,
+ "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
+ "git_http_url":"http://example.com/gitlab-org/gitlab-test.git",
+ "namespace":"Gitlab Org",
+ "visibility_level":10,
+ "path_with_namespace":"gitlab-org/gitlab-test",
+ "default_branch":"master",
+ "homepage":"http://example.com/gitlab-org/gitlab-test",
+ "url":"http://example.com/gitlab-org/gitlab-test.git",
+ "ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
+ "http_url":"http://example.com/gitlab-org/gitlab-test.git"
+ },
+ "repository":{
+ "name": "Gitlab Test",
+ "url": "http://localhost/gitlab-org/gitlab-test.git",
+ "description": "Aut reprehenderit ut est.",
+ "homepage": "http://example.com/gitlab-org/gitlab-test"
+ },
+ "object_attributes": {
+ "id": 1244,
+ "note": "This MR needs work.",
+ "noteable_type": "MergeRequest",
+ "author_id": 1,
+ "created_at": "2015-05-17 18:21:36 UTC",
+ "updated_at": "2015-05-17 18:21:36 UTC",
+ "project_id": 5,
+ "attachment": null,
+ "line_code": null,
+ "commit_id": "",
+ "noteable_id": 7,
+ "system": false,
+ "st_diff": null,
+ "url": "http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244"
+ },
+ "merge_request": {
+ "id": 7,
+ "target_branch": "markdown",
+ "source_branch": "master",
+ "source_project_id": 5,
+ "author_id": 8,
+ "assignee_id": 28,
+ "title": "Tempora et eos debitis quae laborum et.",
+ "created_at": "2015-03-01 20:12:53 UTC",
+ "updated_at": "2015-03-21 18:27:27 UTC",
+ "milestone_id": 11,
+ "state": "opened",
+ "merge_status": "cannot_be_merged",
+ "target_project_id": 5,
+ "iid": 1,
+ "description": "Et voluptas corrupti assumenda temporibus. Architecto cum animi eveniet amet asperiores. Vitae numquam voluptate est natus sit et ad id.",
+ "position": 0,
+ "locked_at": null,
+ "source":{
+ "name":"Gitlab Test",
+ "description":"Aut reprehenderit ut est.",
+ "web_url":"http://example.com/gitlab-org/gitlab-test",
+ "avatar_url":null,
+ "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
+ "git_http_url":"http://example.com/gitlab-org/gitlab-test.git",
+ "namespace":"Gitlab Org",
+ "visibility_level":10,
+ "path_with_namespace":"gitlab-org/gitlab-test",
+ "default_branch":"master",
+ "homepage":"http://example.com/gitlab-org/gitlab-test",
+ "url":"http://example.com/gitlab-org/gitlab-test.git",
+ "ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
+ "http_url":"http://example.com/gitlab-org/gitlab-test.git"
+ },
+ "target": {
+ "name":"Gitlab Test",
+ "description":"Aut reprehenderit ut est.",
+ "web_url":"http://example.com/gitlab-org/gitlab-test",
+ "avatar_url":null,
+ "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
+ "git_http_url":"http://example.com/gitlab-org/gitlab-test.git",
+ "namespace":"Gitlab Org",
+ "visibility_level":10,
+ "path_with_namespace":"gitlab-org/gitlab-test",
+ "default_branch":"master",
+ "homepage":"http://example.com/gitlab-org/gitlab-test",
+ "url":"http://example.com/gitlab-org/gitlab-test.git",
+ "ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
+ "http_url":"http://example.com/gitlab-org/gitlab-test.git"
+ },
+ "last_commit": {
+ "id": "562e173be03b8ff2efb05345d12df18815438a4b",
+ "message": "Merge branch 'another-branch' into 'master'\n\nCheck in this test\n",
+ "timestamp": "2015-04-08T21: 00:25-07:00",
+ "url": "http://example.com/gitlab-org/gitlab-test/commit/562e173be03b8ff2efb05345d12df18815438a4b",
+ "author": {
+ "name": "John Smith",
+ "email": "john@example.com"
+ }
+ },
+ "work_in_progress": false,
+ "assignee": {
+ "name": "User1",
+ "username": "user1",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ }
+ }
+}
+```
+
+#### Comment on issue
+
+**Request header**:
+
+```
+X-Gitlab-Event: Note Hook
+```
+
+**Request body:**
+
+```json
+{
+ "object_kind": "note",
+ "user": {
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ },
+ "project_id": 5,
+ "project":{
+ "name":"Gitlab Test",
+ "description":"Aut reprehenderit ut est.",
+ "web_url":"http://example.com/gitlab-org/gitlab-test",
+ "avatar_url":null,
+ "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
+ "git_http_url":"http://example.com/gitlab-org/gitlab-test.git",
+ "namespace":"Gitlab Org",
+ "visibility_level":10,
+ "path_with_namespace":"gitlab-org/gitlab-test",
+ "default_branch":"master",
+ "homepage":"http://example.com/gitlab-org/gitlab-test",
+ "url":"http://example.com/gitlab-org/gitlab-test.git",
+ "ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
+ "http_url":"http://example.com/gitlab-org/gitlab-test.git"
+ },
+ "repository":{
+ "name":"diaspora",
+ "url":"git@example.com:mike/diaspora.git",
+ "description":"",
+ "homepage":"http://example.com/mike/diaspora"
+ },
+ "object_attributes": {
+ "id": 1241,
+ "note": "Hello world",
+ "noteable_type": "Issue",
+ "author_id": 1,
+ "created_at": "2015-05-17 17:06:40 UTC",
+ "updated_at": "2015-05-17 17:06:40 UTC",
+ "project_id": 5,
+ "attachment": null,
+ "line_code": null,
+ "commit_id": "",
+ "noteable_id": 92,
+ "system": false,
+ "st_diff": null,
+ "url": "http://example.com/gitlab-org/gitlab-test/issues/17#note_1241"
+ },
+ "issue": {
+ "id": 92,
+ "title": "test",
+ "assignee_ids": [],
+ "assignee_id": null,
+ "author_id": 1,
+ "project_id": 5,
+ "created_at": "2015-04-12 14:53:17 UTC",
+ "updated_at": "2015-04-26 08:28:42 UTC",
+ "position": 0,
+ "branch_name": null,
+ "description": "test",
+ "milestone_id": null,
+ "state": "closed",
+ "iid": 17
+ }
+}
+```
+
+**Note**: `assignee_id` field is deprecated and now shows the first assignee only.
+
+#### Comment on code snippet
+
+**Request header**:
+
+```
+X-Gitlab-Event: Note Hook
+```
+
+**Request body:**
+
+```json
+{
+ "object_kind": "note",
+ "user": {
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ },
+ "project_id": 5,
+ "project":{
+ "name":"Gitlab Test",
+ "description":"Aut reprehenderit ut est.",
+ "web_url":"http://example.com/gitlab-org/gitlab-test",
+ "avatar_url":null,
+ "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
+ "git_http_url":"http://example.com/gitlab-org/gitlab-test.git",
+ "namespace":"Gitlab Org",
+ "visibility_level":10,
+ "path_with_namespace":"gitlab-org/gitlab-test",
+ "default_branch":"master",
+ "homepage":"http://example.com/gitlab-org/gitlab-test",
+ "url":"http://example.com/gitlab-org/gitlab-test.git",
+ "ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
+ "http_url":"http://example.com/gitlab-org/gitlab-test.git"
+ },
+ "repository":{
+ "name":"Gitlab Test",
+ "url":"http://example.com/gitlab-org/gitlab-test.git",
+ "description":"Aut reprehenderit ut est.",
+ "homepage":"http://example.com/gitlab-org/gitlab-test"
+ },
+ "object_attributes": {
+ "id": 1245,
+ "note": "Is this snippet doing what it's supposed to be doing?",
+ "noteable_type": "Snippet",
+ "author_id": 1,
+ "created_at": "2015-05-17 18:35:50 UTC",
+ "updated_at": "2015-05-17 18:35:50 UTC",
+ "project_id": 5,
+ "attachment": null,
+ "line_code": null,
+ "commit_id": "",
+ "noteable_id": 53,
+ "system": false,
+ "st_diff": null,
+ "url": "http://example.com/gitlab-org/gitlab-test/snippets/53#note_1245"
+ },
+ "snippet": {
+ "id": 53,
+ "title": "test",
+ "content": "puts 'Hello world'",
+ "author_id": 1,
+ "project_id": 5,
+ "created_at": "2015-04-09 02:40:38 UTC",
+ "updated_at": "2015-04-09 02:40:38 UTC",
+ "file_name": "test.rb",
+ "expires_at": null,
+ "type": "ProjectSnippet",
+ "visibility_level": 0
+ }
+}
+```
+
+### Merge request events
+
+Triggered when a new merge request is created, an existing merge request was updated/merged/closed or a commit is added in the source branch.
+
+**Request header**:
+
+```
+X-Gitlab-Event: Merge Request Hook
+```
+
+**Request body:**
+
+```json
+{
+ "object_kind": "merge_request",
+ "user": {
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ },
+ "object_attributes": {
+ "id": 99,
+ "target_branch": "master",
+ "source_branch": "ms-viewport",
+ "source_project_id": 14,
+ "author_id": 51,
+ "assignee_id": 6,
+ "title": "MS-Viewport",
+ "created_at": "2013-12-03T17:23:34Z",
+ "updated_at": "2013-12-03T17:23:34Z",
+ "st_commits": null,
+ "st_diffs": null,
+ "milestone_id": null,
+ "state": "opened",
+ "merge_status": "unchecked",
+ "target_project_id": 14,
+ "iid": 1,
+ "description": "",
+ "source":{
+ "name":"Awesome Project",
+ "description":"Aut reprehenderit ut est.",
+ "web_url":"http://example.com/awesome_space/awesome_project",
+ "avatar_url":null,
+ "git_ssh_url":"git@example.com:awesome_space/awesome_project.git",
+ "git_http_url":"http://example.com/awesome_space/awesome_project.git",
+ "namespace":"Awesome Space",
+ "visibility_level":20,
+ "path_with_namespace":"awesome_space/awesome_project",
+ "default_branch":"master",
+ "homepage":"http://example.com/awesome_space/awesome_project",
+ "url":"http://example.com/awesome_space/awesome_project.git",
+ "ssh_url":"git@example.com:awesome_space/awesome_project.git",
+ "http_url":"http://example.com/awesome_space/awesome_project.git"
+ },
+ "target": {
+ "name":"Awesome Project",
+ "description":"Aut reprehenderit ut est.",
+ "web_url":"http://example.com/awesome_space/awesome_project",
+ "avatar_url":null,
+ "git_ssh_url":"git@example.com:awesome_space/awesome_project.git",
+ "git_http_url":"http://example.com/awesome_space/awesome_project.git",
+ "namespace":"Awesome Space",
+ "visibility_level":20,
+ "path_with_namespace":"awesome_space/awesome_project",
+ "default_branch":"master",
+ "homepage":"http://example.com/awesome_space/awesome_project",
+ "url":"http://example.com/awesome_space/awesome_project.git",
+ "ssh_url":"git@example.com:awesome_space/awesome_project.git",
+ "http_url":"http://example.com/awesome_space/awesome_project.git"
+ },
+ "last_commit": {
+ "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
+ "message": "fixed readme",
+ "timestamp": "2012-01-03T23:36:29+02:00",
+ "url": "http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
+ "author": {
+ "name": "GitLab dev user",
+ "email": "gitlabdev@dv6700.(none)"
+ }
+ },
+ "work_in_progress": false,
+ "url": "http://example.com/diaspora/merge_requests/1",
+ "action": "open",
+ "assignee": {
+ "name": "User1",
+ "username": "user1",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ }
+ }
+}
+```
+
+### Wiki Page events
+
+Triggered when a wiki page is created, updated or deleted.
+
+**Request Header**:
+
+```
+X-Gitlab-Event: Wiki Page Hook
+```
+
+**Request Body**:
+
+```json
+{
+ "object_kind": "wiki_page",
+ "user": {
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon"
+ },
+ "project": {
+ "name": "awesome-project",
+ "description": "This is awesome",
+ "web_url": "http://example.com/root/awesome-project",
+ "avatar_url": null,
+ "git_ssh_url": "git@example.com:root/awesome-project.git",
+ "git_http_url": "http://example.com/root/awesome-project.git",
+ "namespace": "root",
+ "visibility_level": 0,
+ "path_with_namespace": "root/awesome-project",
+ "default_branch": "master",
+ "homepage": "http://example.com/root/awesome-project",
+ "url": "git@example.com:root/awesome-project.git",
+ "ssh_url": "git@example.com:root/awesome-project.git",
+ "http_url": "http://example.com/root/awesome-project.git"
+ },
+ "wiki": {
+ "web_url": "http://example.com/root/awesome-project/wikis/home",
+ "git_ssh_url": "git@example.com:root/awesome-project.wiki.git",
+ "git_http_url": "http://example.com/root/awesome-project.wiki.git",
+ "path_with_namespace": "root/awesome-project.wiki",
+ "default_branch": "master"
+ },
+ "object_attributes": {
+ "title": "Awesome",
+ "content": "awesome content goes here",
+ "format": "markdown",
+ "message": "adding an awesome page to the wiki",
+ "slug": "awesome",
+ "url": "http://example.com/root/awesome-project/wikis/awesome",
+ "action": "create"
+ }
+}
+```
+
+### Pipeline events
+
+Triggered on status change of Pipeline.
+
+**Request Header**:
+
+```
+X-Gitlab-Event: Pipeline Hook
+```
+
+**Request Body**:
+
+```json
+{
+ "object_kind": "pipeline",
+ "object_attributes":{
+ "id": 31,
+ "ref": "master",
+ "tag": false,
+ "sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
+ "before_sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
+ "status": "success",
+ "stages":[
+ "build",
+ "test",
+ "deploy"
+ ],
+ "created_at": "2016-08-12 15:23:28 UTC",
+ "finished_at": "2016-08-12 15:26:29 UTC",
+ "duration": 63
+ },
+ "user":{
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
+ },
+ "project":{
+ "name": "Gitlab Test",
+ "description": "Atque in sunt eos similique dolores voluptatem.",
+ "web_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test",
+ "avatar_url": null,
+ "git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git",
+ "git_http_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test.git",
+ "namespace": "Gitlab Org",
+ "visibility_level": 20,
+ "path_with_namespace": "gitlab-org/gitlab-test",
+ "default_branch": "master"
+ },
+ "commit":{
+ "id": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
+ "message": "test\n",
+ "timestamp": "2016-08-12T17:23:21+02:00",
+ "url": "http://example.com/gitlab-org/gitlab-test/commit/bcbb5ec396a2c0f828686f14fac9b80b780504f2",
+ "author":{
+ "name": "User",
+ "email": "user@gitlab.com"
+ }
+ },
+ "builds":[
+ {
+ "id": 380,
+ "stage": "deploy",
+ "name": "production",
+ "status": "skipped",
+ "created_at": "2016-08-12 15:23:28 UTC",
+ "started_at": null,
+ "finished_at": null,
+ "when": "manual",
+ "manual": true,
+ "user":{
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
+ },
+ "runner": null,
+ "artifacts_file":{
+ "filename": null,
+ "size": null
+ }
+ },
+ {
+ "id": 377,
+ "stage": "test",
+ "name": "test-image",
+ "status": "success",
+ "created_at": "2016-08-12 15:23:28 UTC",
+ "started_at": "2016-08-12 15:26:12 UTC",
+ "finished_at": null,
+ "when": "on_success",
+ "manual": false,
+ "user":{
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
+ },
+ "runner": null,
+ "artifacts_file":{
+ "filename": null,
+ "size": null
+ }
+ },
+ {
+ "id": 378,
+ "stage": "test",
+ "name": "test-build",
+ "status": "success",
+ "created_at": "2016-08-12 15:23:28 UTC",
+ "started_at": "2016-08-12 15:26:12 UTC",
+ "finished_at": "2016-08-12 15:26:29 UTC",
+ "when": "on_success",
+ "manual": false,
+ "user":{
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
+ },
+ "runner": null,
+ "artifacts_file":{
+ "filename": null,
+ "size": null
+ }
+ },
+ {
+ "id": 376,
+ "stage": "build",
+ "name": "build-image",
+ "status": "success",
+ "created_at": "2016-08-12 15:23:28 UTC",
+ "started_at": "2016-08-12 15:24:56 UTC",
+ "finished_at": "2016-08-12 15:25:26 UTC",
+ "when": "on_success",
+ "manual": false,
+ "user":{
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
+ },
+ "runner": null,
+ "artifacts_file":{
+ "filename": null,
+ "size": null
+ }
+ },
+ {
+ "id": 379,
+ "stage": "deploy",
+ "name": "staging",
+ "status": "created",
+ "created_at": "2016-08-12 15:23:28 UTC",
+ "started_at": null,
+ "finished_at": null,
+ "when": "on_success",
+ "manual": false,
+ "user":{
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
+ },
+ "runner": null,
+ "artifacts_file":{
+ "filename": null,
+ "size": null
+ }
+ }
+ ]
+}
+```
+
+### Build events
+
+Triggered on status change of a Build.
+
+**Request Header**:
+
+```
+X-Gitlab-Event: Build Hook
+```
+
+**Request Body**:
+
+```json
+{
+ "object_kind": "build",
+ "ref": "gitlab-script-trigger",
+ "tag": false,
+ "before_sha": "2293ada6b400935a1378653304eaf6221e0fdb8f",
+ "sha": "2293ada6b400935a1378653304eaf6221e0fdb8f",
+ "build_id": 1977,
+ "build_name": "test",
+ "build_stage": "test",
+ "build_status": "created",
+ "build_started_at": null,
+ "build_finished_at": null,
+ "build_duration": null,
+ "build_allow_failure": false,
+ "project_id": 380,
+ "project_name": "gitlab-org/gitlab-test",
+ "user": {
+ "id": 3,
+ "name": "User",
+ "email": "user@gitlab.com"
+ },
+ "commit": {
+ "id": 2366,
+ "sha": "2293ada6b400935a1378653304eaf6221e0fdb8f",
+ "message": "test\n",
+ "author_name": "User",
+ "author_email": "user@gitlab.com",
+ "status": "created",
+ "duration": null,
+ "started_at": null,
+ "finished_at": null
+ },
+ "repository": {
+ "name": "gitlab_test",
+ "git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git",
+ "description": "Atque in sunt eos similique dolores voluptatem.",
+ "homepage": "http://192.168.64.1:3005/gitlab-org/gitlab-test",
+ "git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git",
+ "git_http_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test.git",
+ "visibility_level": 20
+ }
+}
+```
+
+## Troubleshoot webhooks
+
+Gitlab stores each perform of the webhook.
+You can find records for last 2 days in "Recent Deliveries" section on the edit page of each webhook.
+
+![Recent deliveries](img/webhook_logs.png)
+
+In this section you can see HTTP status code (green for 200-299 codes, red for the others, `internal error` for failed deliveries ), triggered event, a time when the event was called, elapsed time of the request.
+
+If you need more information about execution, you can click `View details` link.
+On this page, you can see data that GitLab sends (request headers and body) and data that it received (response headers and body).
+
+From this page, you can repeat delivery with the same data by clicking `Resend Request` button.
+
+>**Note:** If URL or secret token of the webhook were updated, data will be delivered to the new address.
+
+## Example webhook receiver
+
+If you want to see GitLab's webhooks in action for testing purposes you can use
+a simple echo script running in a console session. For the following script to
+work you need to have Ruby installed.
+
+Save the following file as `print_http_body.rb`:
+
+```ruby
+require 'webrick'
+
+server = WEBrick::HTTPServer.new(:Port => ARGV.first)
+server.mount_proc '/' do |req, res|
+ puts req.body
+end
+
+trap 'INT' do
+ server.shutdown
+end
+server.start
+```
+
+Pick an unused port (e.g. 8000) and start the script: `ruby print_http_body.rb
+8000`. Then add your server as a webhook receiver in GitLab as
+`http://my.host:8000/`.
+
+When you press 'Test Hook' in GitLab, you should see something like this in the
+console:
+
+```
+{"before":"077a85dd266e6f3573ef7e9ef8ce3343ad659c4e","after":"95cd4a99e93bc4bbabacfa2cd10e6725b1403c60",<SNIP>}
+example.com - - [14/May/2014:07:45:26 EDT] "POST / HTTP/1.1" 200 0
+- -> /
+```
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index 4a6c0d88241..ebea7062ecb 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -1,6 +1,8 @@
# Issue board
-> [Introduced][ce-5554] in GitLab 8.11.
+>**Notes:**
+- [Introduced][ce-5554] in GitLab 8.11.
+- The Backlog column was replaced by the **Add issues** button in GitLab 8.17.
The GitLab Issue Board is a software project management tool used to plan,
organize, and visualize a workflow for a feature or product release.
@@ -26,15 +28,14 @@ Below is a table of the definitions used for GitLab's Issue Board.
| -------------- | ------------- |
| **Issue Board** | It represents a different view for your issues. It can have multiple lists with each list consisting of issues represented by cards. |
| **List** | Each label that exists in the issue tracker can have its own dedicated list. Every list is named after the label it is based on and is represented by a column which contains all the issues associated with that label. You can think of a list like the results you get when you filter the issues by a label in your issue tracker. |
-| **Card** | Every card represents an issue and it is shown under the list for which it has a label. The information you can see on a card consists of the issue number, the issue title, the assignee and the labels associated with it. You can drag cards around from one list to another. Issues inside lists are [ordered by priority](labels.md#prioritize-labels). |
+| **Card** | Every card represents an issue and it is shown under the list for which it has a label. The information you can see on a card consists of the issue number, the issue title, the assignee and the labels associated with it. You can drag cards around from one list to another. You can re-order cards within a list. |
-There are three types of lists, the ones you create based on your labels, and
-two default:
+There are two types of lists, the ones you create based on your labels, and
+two defaults:
-- **Backlog** (default): shows all issues that do not fall in one of the other lists. Always appears on the very left.
-- **Done** (default): shows all closed issues. Always appears on the very right.
-Label list: a list based on a label. It shows all issues with that label.
- Label list: a list based on a label. It shows all opened issues with that label.
+- **Backlog** (default): shows all open issues that does not belong to one of lists. Always appears on the very left.
+- **Closed** (default): shows all closed issues. Always appears on the very right.
![GitLab Issue Board](img/issue_board.png)
@@ -45,6 +46,7 @@ In short, here's a list of actions you can take in an Issue Board:
- [Create a new list](#creating-a-new-list).
- [Delete an existing list](#deleting-a-list).
- Drag issues between lists.
+- Re-order issues in lists.
- Drag and reorder the lists themselves.
- Change issue labels on-the-fly while dragging issues between lists.
- Close an issue if you drag it to the **Done** list.
@@ -55,10 +57,10 @@ In short, here's a list of actions you can take in an Issue Board:
If you are not able to perform one or more of the things above, make sure you
have the right [permissions](#permissions).
-## First time using the Issue Board
+## First time using the issue board
-The first time you navigate to your Issue Board, you will be presented with the
-two default lists (**Backlog** and **Done**) and a welcoming message that gives
+The first time you navigate to your Issue Board, you will be presented with
+a default list (**Done**) and a welcoming message that gives
you two options. You can either create a predefined set of labels and create
their corresponding lists to the Issue Board or opt-out and use your own lists.
@@ -72,7 +74,7 @@ the list will be created and filled with the issues that have that label.
## Creating a new list
-Create a new list by clicking on the **Create new list** button at the upper
+Create a new list by clicking on the **Add list** button at the upper
right corner of the Issue Board.
![Issue Board welcome message](img/issue_board_add_list.png)
@@ -93,23 +95,33 @@ in the list's heading. A confirmation dialog will appear for you to confirm.
Deleting a list doesn't have any effect in issues and labels, it's just the
list view that is removed. You can always add it back later if you need.
-## Searching issues in the Backlog list
+## Adding issues to a list
-The very first time you start using the Issue Board, it is very likely your
-issue tracker is already populated with labels and issues. In that case,
-**Backlog** will have all the issues that don't belong to another list, and
-**Done** will have all the closed ones.
+You can add issues to a list by clicking the **Add issues** button that is
+present in the upper right corner of the issue board. This will open up a modal
+window where you can see all the issues that do not belong to any list.
-For performance and visibility reasons, each list shows the first 20 issues
-by default. If you have more than 20, you have to start scrolling down for the
-next 20 issues to appear. This can be cumbersome if your issue tracker hosts
-hundreds of issues, and for that reason it is easier to search for issues to
-move from **Backlog** to another list.
+Select one or more issues by clicking on the cards and then click **Add issues**
+to add them to the selected list. You can limit the issues you want to add to
+the list by filtering by author, assignee, milestone and label.
-Start typing in the search bar under the **Backlog** list and the relevant
-issues will appear.
+![Bulk adding issues to lists](img/issue_boards_add_issues_modal.png)
-![Issue Board search Backlog](img/issue_board_search_backlog.png)
+## Removing an issue from a list
+
+Removing an issue from a list can be done by clicking on the issue card and then
+clicking the **Remove from board** button in the sidebar. Under the hood, the
+respective label is removed, and as such it's also removed from the list and the
+board itself.
+
+![Remove issue from list](img/issue_boards_remove_issue.png)
+
+## Re-ordering an issue in a list
+
+> Introduced in GitLab 9.0.
+
+Issues can be re-ordered inside of lists. This is as simple as dragging and dropping
+an issue into the order you want.
## Filtering issues
@@ -142,8 +154,8 @@ A typical workflow of using the Issue Board would be:
and gets automatically closed.
For instance you can create a list based on the label of 'Frontend' and one for
-'Backend'. A designer can start working on an issue by dragging it from
-**Backlog** to 'Frontend'. That way, everyone knows that this issue is now being
+'Backend'. A designer can start working on an issue by adding it to the
+'Frontend' list. That way, everyone knows that this issue is now being
worked on by the designers. Then, once they're done, all they have to do is
drag it over to the next list, 'Backend', where a backend developer can
eventually pick it up. Once they’re done, they move it to **Done**, to close the
@@ -173,7 +185,6 @@ A few things to remember:
- Clicking on the issue title inside a card will take you to that issue.
- Clicking on a label inside a card will quickly filter the entire Issue Board
and show only the issues from all lists that have that label.
-- Issues inside lists are [ordered by priority][label-priority].
- For performance and visibility reasons, each list shows the first 20 issues
by default. If you have more than 20 issues start scrolling down and the next
20 will appear.
diff --git a/doc/user/project/issues/closing_issues.md b/doc/user/project/issues/closing_issues.md
new file mode 100644
index 00000000000..dcfa5ff59b2
--- /dev/null
+++ b/doc/user/project/issues/closing_issues.md
@@ -0,0 +1,59 @@
+# Closing Issues
+
+Please read through the [GitLab Issue Documentation](index.md) for an overview on GitLab Issues.
+
+## Directly
+
+Whenever you decide that's no longer need for that issue,
+close the issue using the close button:
+
+![close issue - button](img/button_close_issue.png)
+
+## Via Merge Request
+
+When a merge request resolves the discussion over an issue, you can
+make it close that issue(s) when merged.
+
+All you need is to use a [keyword](automatic_issue_closing.md)
+accompanying the issue number, add to the description of that MR.
+
+In this example, the keyword "closes" prefixing the issue number will create a relationship
+in such a way that the merge request will close the issue when merged.
+
+Mentioning various issues in the same line also works for this purpose:
+
+```md
+Closes #333, #444, #555 and #666
+```
+
+If the issue is in a different repository rather then the MR's,
+add the full URL for that issue(s):
+
+```md
+Closes #333, #444, and https://gitlab.com/<username>/<projectname>/issues/<xxx>
+```
+
+All the following keywords will produce the same behaviour:
+
+- Close, Closes, Closed, Closing, close, closes, closed, closing
+- Fix, Fixes, Fixed, Fixing, fix, fixes, fixed, fixing
+- Resolve, Resolves, Resolved, Resolving, resolve, resolves, resolved, resolving
+
+![merge request closing issue when merged](img/merge_request_closes_issue.png)
+
+If you use any other word before the issue number, the issue and the MR will
+link to each other, but the MR will NOT close the issue(s) when merged.
+
+![mention issues in MRs - closing and related](img/closing_and_related_issues.png)
+
+## From the Issue Board
+
+You can close an issue from [Issue Boards](../issue_board.md) by draging an issue card
+from its list and dropping into **Closed**.
+
+![close issue from the Issue Board](img/close_issue_from_board.gif)
+
+## Customizing the issue closing patern
+
+Alternatively, a GitLab **administrator** can
+[customize the issue closing patern](../../../administration/issue_closing_pattern.md).
diff --git a/doc/user/project/issues/confidential_issues.md b/doc/user/project/issues/confidential_issues.md
new file mode 100644
index 00000000000..1760b182114
--- /dev/null
+++ b/doc/user/project/issues/confidential_issues.md
@@ -0,0 +1,68 @@
+# Confidential issues
+
+> [Introduced][ce-3282] in GitLab 8.6.
+
+Confidential issues are issues visible only to members of a project with
+[sufficient permissions](#permissions-and-access-to-confidential-issues).
+Confidential issues can be used by open source projects and companies alike to
+keep security vulnerabilities private or prevent surprises from leaking out.
+
+## Making an issue confidential
+
+You can make an issue confidential either by creating a new issue or editing
+an existing one.
+
+When you create a new issue, a checkbox right below the text area is available
+to mark the issue as confidential. Check that box and hit the **Submit issue**
+button to create the issue. For existing issues, edit them, check the
+confidential checkbox and hit **Save changes**.
+
+![Creating a new confidential issue](img/confidential_issues_create.png)
+
+## Making an issue non-confidential
+
+To make an issue non-confidential, all you have to do is edit it and unmark
+the confidential checkbox. Once you save the issue, it will gain the default
+visibility level you have chosen for your project.
+
+Every change from regular to confidential and vice versa, is indicated by a
+system note in the issue's comments.
+
+![Confidential issues system notes](img/confidential_issues_system_notes.png)
+
+## Indications of a confidential issue
+
+>**Note:** If you don't have [enough permissions](#permissions-and-access-to-confidential-issues),
+you won't be able to see the confidential issues at all.
+
+There are a few things that visually separate a confidential issue from a
+regular one. In the issues index page view, you can see the eye-slash icon
+next to the issues that are marked as confidential.
+
+![Confidential issues index page](img/confidential_issues_index_page.png)
+
+---
+
+Likewise, while inside the issue, you can see the eye-slash icon right next to
+the issue number, but there is also an indicator in the comment area that the
+issue you are commenting on is confidential.
+
+![Confidential issue page](img/confidential_issues_issue_page.png)
+
+## Permissions and access to confidential issues
+
+There are two kinds of level access for confidential issues. The general rule
+is that confidential issues are visible only to members of a project with at
+least [Reporter access][permissions]. However, a guest user can also create
+confidential issues, but can only view the ones that they created themselves.
+
+Confidential issues are also hidden in search results for unprivileged users.
+For example, here's what a user with Master and Guest access sees in the
+project's search results respectively.
+
+| Master access | Guest access |
+| :-----------: | :----------: |
+| ![Confidential issues search master](img/confidential_issues_search_master.png) | ![Confidential issues search guest](img/confidential_issues_search_guest.png) |
+
+[permissions]: ../../permissions.md#project
+[ce-3282]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3282
diff --git a/doc/user/project/issues/create_new_issue.md b/doc/user/project/issues/create_new_issue.md
new file mode 100644
index 00000000000..9af088374a1
--- /dev/null
+++ b/doc/user/project/issues/create_new_issue.md
@@ -0,0 +1,38 @@
+# Create a new Issue
+
+Please read through the [GitLab Issue Documentation](index.md) for an overview on GitLab Issues.
+
+When you create a new issue, you'll be prompted to fill in
+the information illustrated on the image below.
+
+![New issue from the issues list](img/new_issue.png)
+
+Read through the [issues functionalities documentation](issues_functionalities.md#issues-functionalities)
+to understand these fields one by one.
+
+## New issue from the Issue Tracker
+
+Navigate to your **Project's Dashboard** > **Issues** > **New Issue** to create a new issue:
+
+![New issue from the issue list view](img/new_issue_from_tracker_list.png)
+
+## New issue from an opened issue
+
+From an **opened issue** in your project, click **New Issue** to create a new
+issue in the same project:
+
+![New issue from an open issue](img/new_issue_from_open_issue.png)
+
+## New issue from the project's dashboard
+
+From your **Project's Dashboard**, click the plus sign (**+**) to open a dropdown
+menu with a few options. Select **New Issue** to create an issue in that project:
+
+![New issue from a project's dashboard](img/new_issue_from_projects_dashboard.png)
+
+## New issue from the Issue Board
+
+From an Issue Board, create a new issue by clicking on the plus sign (**+**) on the top of a list.
+It opens a new issue for that project labeled after its respective list.
+
+![From the issue board](img/new_issue_from_issue_board.png)
diff --git a/doc/user/project/issues/crosslinking_issues.md b/doc/user/project/issues/crosslinking_issues.md
new file mode 100644
index 00000000000..5cc7ea383ae
--- /dev/null
+++ b/doc/user/project/issues/crosslinking_issues.md
@@ -0,0 +1,63 @@
+# Crosslinking Issues
+
+Please read through the [GitLab Issue Documentation](index.md) for an overview on GitLab Issues.
+
+## From Commit Messages
+
+Every time you mention an issue in your commit message, you're creating
+a relationship between the two stages of the development workflow: the
+issue itself and the first commit related to that issue.
+
+If the issue and the code you're committing are both in the same project,
+you simply add `#xxx` to the commit message, where `xxx` is the issue number.
+If they are not in the same project, you can add the full URL to the issue
+(`https://gitlab.com/<username>/<projectname>/issues/<xxx>`).
+
+```shell
+git commit -m "this is my commit message. Ref #xxx"
+```
+
+or
+
+```shell
+git commit -m "this is my commit message. Related to https://gitlab.com/<username>/<projectname>/issues/<xxx>"
+```
+
+Of course, you can replace `gitlab.com` with the URL of your own GitLab instance.
+
+**Note:** Linking your first commit to your issue is going to be relevant
+for tracking your process far ahead with
+[GitLab Cycle Analytics](https://about.gitlab.com/features/cycle-analytics/)).
+It will measure the time taken for planning the implementation of that issue,
+which is the time between creating an issue and making the first commit.
+
+## From Related Issues
+
+Mentioning related issues in merge requests and other issues is useful
+for your team members and collaborators to know that there are opened
+issues around that same idea.
+
+You do that as explained above, when
+[mentioning an issue from a commit message](#from-commit-messages).
+
+When mentioning the issue "A" in a issue "B", the issue "A" will also
+display a notification in its tracker. The same is valid for mentioning
+issues in merge requests.
+
+![issue mentioned in issue](img/mention_in_issue.png)
+
+## From Merge Requests
+
+Mentioning issues in merge request comments work exactly the same way
+they do for [related issues](#from-related-issues).
+
+When you mention an issue in a merge request description, you can either
+[close the issue as soon as the merge request is merged](closing_issues.md#via-merge-request),
+or simply link both issue and merge request as described in the
+[closing issues documentation](closing_issues.md#from-related-issues).
+
+![issue mentioned in MR](img/mention_in_merge_request.png)
+
+### Close an issue by merging a merge request
+
+To [close an issue when a merge request is merged](closing_issues.md#via-merge-request), use the [automatic issue closing patern](automatic_issue_closing.md).
diff --git a/doc/user/project/issues/due_dates.md b/doc/user/project/issues/due_dates.md
new file mode 100644
index 00000000000..e0c405353ce
--- /dev/null
+++ b/doc/user/project/issues/due_dates.md
@@ -0,0 +1,39 @@
+# Due dates
+
+> [Introduced][ce-3614] in GitLab 8.7.
+
+Please read through the [GitLab Issue Documentation](index.md) for an overview on GitLab Issues.
+
+Due dates can be used in issues to keep track of deadlines and make sure
+features are shipped on time. Due dates require at least [Reporter permissions][permissions]
+to be able to edit them. On the contrary, they can be seen by everybody.
+
+## Setting a due date
+
+When creating or editing an issue, you can see the due date field from where
+a calendar will appear to help you choose the date you want. To remove it,
+select the date text and delete it.
+
+![Create a due date](img/due_dates_create.png)
+
+A quicker way to set a due date is via the issue sidebar. Simply expand the
+sidebar and select **Edit** to pick a due date or remove the existing one.
+Changes are saved immediately.
+
+![Edit a due date via the sidebar](img/due_dates_edit_sidebar.png)
+
+## Making use of due dates
+
+Issues that have a due date can be distinctively seen in the issue tracker
+displaying a date next to them. Issues where the date is overdue will have
+the icon and the date colored red. You can sort issues by those that are
+_Due soon_ or _Due later_ from the dropdown menu in the right.
+
+![Issues with due dates in the issues index page](img/due_dates_issues_index_page.png)
+
+Due dates also appear in your [todos list](../../../workflow/todos.md).
+
+![Issues with due dates in the todos](img/due_dates_todos.png)
+
+[ce-3614]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3614
+[permissions]: ../../permissions.md#project
diff --git a/doc/user/project/issues/img/button_close_issue.png b/doc/user/project/issues/img/button_close_issue.png
new file mode 100755
index 00000000000..8fb2e23f58a
--- /dev/null
+++ b/doc/user/project/issues/img/button_close_issue.png
Binary files differ
diff --git a/doc/user/project/issues/img/close_issue_from_board.gif b/doc/user/project/issues/img/close_issue_from_board.gif
new file mode 100644
index 00000000000..4814b42687b
--- /dev/null
+++ b/doc/user/project/issues/img/close_issue_from_board.gif
Binary files differ
diff --git a/doc/user/project/issues/img/closing_and_related_issues.png b/doc/user/project/issues/img/closing_and_related_issues.png
new file mode 100755
index 00000000000..c6543e85fdb
--- /dev/null
+++ b/doc/user/project/issues/img/closing_and_related_issues.png
Binary files differ
diff --git a/doc/user/project/issues/img/confidential_issues_create.png b/doc/user/project/issues/img/confidential_issues_create.png
new file mode 100755
index 00000000000..0a141eb39f8
--- /dev/null
+++ b/doc/user/project/issues/img/confidential_issues_create.png
Binary files differ
diff --git a/doc/user/project/issues/img/confidential_issues_index_page.png b/doc/user/project/issues/img/confidential_issues_index_page.png
new file mode 100755
index 00000000000..e4b492a2769
--- /dev/null
+++ b/doc/user/project/issues/img/confidential_issues_index_page.png
Binary files differ
diff --git a/doc/user/project/issues/img/confidential_issues_issue_page.png b/doc/user/project/issues/img/confidential_issues_issue_page.png
new file mode 100755
index 00000000000..f04ec8ff32b
--- /dev/null
+++ b/doc/user/project/issues/img/confidential_issues_issue_page.png
Binary files differ
diff --git a/doc/user/project/issues/img/confidential_issues_search_guest.png b/doc/user/project/issues/img/confidential_issues_search_guest.png
new file mode 100755
index 00000000000..dc1b4ba8ad7
--- /dev/null
+++ b/doc/user/project/issues/img/confidential_issues_search_guest.png
Binary files differ
diff --git a/doc/user/project/issues/img/confidential_issues_search_master.png b/doc/user/project/issues/img/confidential_issues_search_master.png
new file mode 100755
index 00000000000..fc01f4da9db
--- /dev/null
+++ b/doc/user/project/issues/img/confidential_issues_search_master.png
Binary files differ
diff --git a/doc/user/project/issues/img/confidential_issues_system_notes.png b/doc/user/project/issues/img/confidential_issues_system_notes.png
new file mode 100755
index 00000000000..82e0dd8e85e
--- /dev/null
+++ b/doc/user/project/issues/img/confidential_issues_system_notes.png
Binary files differ
diff --git a/doc/user/project/issues/img/due_dates_create.png b/doc/user/project/issues/img/due_dates_create.png
new file mode 100755
index 00000000000..ece35d44213
--- /dev/null
+++ b/doc/user/project/issues/img/due_dates_create.png
Binary files differ
diff --git a/doc/user/project/issues/img/due_dates_edit_sidebar.png b/doc/user/project/issues/img/due_dates_edit_sidebar.png
new file mode 100755
index 00000000000..d1c7d1eb7e9
--- /dev/null
+++ b/doc/user/project/issues/img/due_dates_edit_sidebar.png
Binary files differ
diff --git a/doc/user/project/issues/img/due_dates_issues_index_page.png b/doc/user/project/issues/img/due_dates_issues_index_page.png
new file mode 100755
index 00000000000..94679436b32
--- /dev/null
+++ b/doc/user/project/issues/img/due_dates_issues_index_page.png
Binary files differ
diff --git a/doc/user/project/issues/img/due_dates_todos.png b/doc/user/project/issues/img/due_dates_todos.png
new file mode 100755
index 00000000000..4c124c97f67
--- /dev/null
+++ b/doc/user/project/issues/img/due_dates_todos.png
Binary files differ
diff --git a/doc/user/project/issues/img/issue_board.png b/doc/user/project/issues/img/issue_board.png
new file mode 100755
index 00000000000..1759b28a9ef
--- /dev/null
+++ b/doc/user/project/issues/img/issue_board.png
Binary files differ
diff --git a/doc/user/project/issues/img/issue_template.png b/doc/user/project/issues/img/issue_template.png
new file mode 100755
index 00000000000..c63229a4af2
--- /dev/null
+++ b/doc/user/project/issues/img/issue_template.png
Binary files differ
diff --git a/doc/user/project/issues/img/issue_tracker.png b/doc/user/project/issues/img/issue_tracker.png
new file mode 100755
index 00000000000..ab25cb64d13
--- /dev/null
+++ b/doc/user/project/issues/img/issue_tracker.png
Binary files differ
diff --git a/doc/user/project/issues/img/issues_main_view.png b/doc/user/project/issues/img/issues_main_view.png
new file mode 100644
index 00000000000..4faa42e40ee
--- /dev/null
+++ b/doc/user/project/issues/img/issues_main_view.png
Binary files differ
diff --git a/doc/user/project/issues/img/issues_main_view_numbered.jpg b/doc/user/project/issues/img/issues_main_view_numbered.jpg
new file mode 100644
index 00000000000..4b5d7fba459
--- /dev/null
+++ b/doc/user/project/issues/img/issues_main_view_numbered.jpg
Binary files differ
diff --git a/doc/user/project/issues/img/mention_in_issue.png b/doc/user/project/issues/img/mention_in_issue.png
new file mode 100755
index 00000000000..c762a812138
--- /dev/null
+++ b/doc/user/project/issues/img/mention_in_issue.png
Binary files differ
diff --git a/doc/user/project/issues/img/mention_in_merge_request.png b/doc/user/project/issues/img/mention_in_merge_request.png
new file mode 100755
index 00000000000..681e086d6e0
--- /dev/null
+++ b/doc/user/project/issues/img/mention_in_merge_request.png
Binary files differ
diff --git a/doc/user/project/issues/img/merge_request_closes_issue.png b/doc/user/project/issues/img/merge_request_closes_issue.png
new file mode 100755
index 00000000000..6fd27738843
--- /dev/null
+++ b/doc/user/project/issues/img/merge_request_closes_issue.png
Binary files differ
diff --git a/doc/user/project/issues/img/new_issue.png b/doc/user/project/issues/img/new_issue.png
new file mode 100755
index 00000000000..e72ac49d6b9
--- /dev/null
+++ b/doc/user/project/issues/img/new_issue.png
Binary files differ
diff --git a/doc/user/project/issues/img/new_issue_from_issue_board.png b/doc/user/project/issues/img/new_issue_from_issue_board.png
new file mode 100755
index 00000000000..9c2b3ff50fa
--- /dev/null
+++ b/doc/user/project/issues/img/new_issue_from_issue_board.png
Binary files differ
diff --git a/doc/user/project/issues/img/new_issue_from_open_issue.png b/doc/user/project/issues/img/new_issue_from_open_issue.png
new file mode 100755
index 00000000000..2aed5372830
--- /dev/null
+++ b/doc/user/project/issues/img/new_issue_from_open_issue.png
Binary files differ
diff --git a/doc/user/project/issues/img/new_issue_from_projects_dashboard.png b/doc/user/project/issues/img/new_issue_from_projects_dashboard.png
new file mode 100755
index 00000000000..cddf36b7457
--- /dev/null
+++ b/doc/user/project/issues/img/new_issue_from_projects_dashboard.png
Binary files differ
diff --git a/doc/user/project/issues/img/new_issue_from_tracker_list.png b/doc/user/project/issues/img/new_issue_from_tracker_list.png
new file mode 100755
index 00000000000..7e5413f0b7d
--- /dev/null
+++ b/doc/user/project/issues/img/new_issue_from_tracker_list.png
Binary files differ
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
new file mode 100644
index 00000000000..fe87e6f9495
--- /dev/null
+++ b/doc/user/project/issues/index.md
@@ -0,0 +1,104 @@
+# Issues documentation
+
+The GitLab Issue Tracker is an advanced and complete tool
+for tracking the evolution of a new idea or the process
+of solving a problem.
+
+It allows you, your team, and your collaborators to share
+and discuss proposals, before and while implementing them.
+
+Issues and the GitLab Issue Tracker are available in all
+[GitLab Products](https://about.gitlab.com/products/) as
+part of the [GitLab Workflow](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/).
+
+## Use-Cases
+
+Issues can have endless applications. Just to exemplify, these are
+some cases for which creating issues are most used:
+
+- Discussing the implementation of a new idea
+- Submitting feature proposals
+- Asking questions
+- Reporting bugs and malfunction
+- Obtaining support
+- Elaborating new code implementations
+
+See also the blog post [Always start a discussion with an issue](https://about.gitlab.com/2016/03/03/start-with-an-issue/).
+
+## Issue Tracker
+
+The issue tracker is the collection of opened and closed issues created in a project.
+
+![Issue tracker](img/issue_tracker.png)
+
+Find the issue tracker by navigating to your **Project's Dashboard** > **Issues**.
+
+## GitLab Issues Functionalities
+
+The image bellow illustrates how an issue looks like:
+
+![Issue view](img/issues_main_view.png)
+
+Learn more about it on the [GitLab Issues Functionalities documentation](issues_functionalities.md).
+
+## New issue
+
+Read through the [documentation on creating issues](create_new_issue.md).
+
+## Closing issues
+
+Learn distinct ways to [close issues](closing_issues.md) in GitLab.
+
+## Create a merge request from an issue
+
+Learn more about it on the [GitLab Issues Functionalities documentation](issues_functionalities.md#18-new-merge-request).
+
+## Search for an issue
+
+Learn how to [find an issue](../../search/index.md) by searching for and filtering them.
+
+## Advanced features
+
+### Confidential Issues
+
+Whenever you want to keep the discussion presented in a
+issue within your team only, you can make that
+[issue confidential](confidential_issues.md). Even if your project
+is public, that issue will be preserved. The browser will
+respond with a 404 error whenever someone who is not a project
+member with at least [Reporter level](../../permissions.md#project) tries to
+access that issue's URL.
+
+Learn more about them on the [confidential issues documentation](confidential_issues.md).
+
+### Issue templates
+
+Create templates for every new issue. They will be available from
+the dropdown menu **Choose a template** when you create a new issue:
+
+![issue template](img/issue_template.png)
+
+Learn more about them on the [issue templates documentation](../../project/description_templates.md#creating-issue-templates).
+
+### Crosslinking issues
+
+Learn more about [crosslinking](crosslinking_issues.md) issues and merge requests.
+
+### Issue Board
+
+The [GitLab Issue Board](https://about.gitlab.com/features/issueboard/) is a way to
+enhance your workflow by organizing and prioritizing issues in GitLab.
+
+![Issue board](img/issue_board.png)
+
+Find GitLab Issue Boards by navigating to your **Project's Dashboard** > **Issues** > **Board**.
+
+Read through the documentation for [Issue Boards](../issue_board.md)
+to find out more about this feature.
+
+[Multiple Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards)
+are available only in [GitLab Enterprise Edition](https://about.gitlab.com/gitlab-ee/).
+
+### Issue's API
+
+Read through the [API documentation](../../../api/issues.md).
diff --git a/doc/user/project/issues/issues_functionalities.md b/doc/user/project/issues/issues_functionalities.md
new file mode 100644
index 00000000000..294176e61f9
--- /dev/null
+++ b/doc/user/project/issues/issues_functionalities.md
@@ -0,0 +1,176 @@
+# GitLab Issues Functionalities
+
+Please read through the [GitLab Issue Documentation](index.md) for an overview on GitLab Issues.
+
+## Issues Functionalities
+
+The image bellow illustrates how an issue looks like:
+
+![Issue view](img/issues_main_view_numbered.jpg)
+
+You can find all the information on that issue on one screen.
+
+### Issue screen
+
+An issue starts with its status (open or closed), followed by its author,
+and includes many other functionalities, numbered on the image above to
+explain what they mean, one by one.
+
+Many of the elements of the issue screen refresh automatically, such as the title and description, when they are changed by another user.
+Comments and system notes also appear automatically in response to various actions and content updates.
+
+#### 1. New Issue, close issue, edit
+
+- New issue: create a new issue in the same project
+- Close issue: close this issue
+- Edit: edit the same fields available when you create an issue.
+
+#### 2. Todos
+
+- Add todo: add that issue to your [GitLab Todo](../../../workflow/todos.html) list
+- Mark done: mark that issue as done (reflects on the Todo list)
+
+#### 3. Assignee
+
+Whenever someone starts to work on an issue, it can be assigned
+to that person. The assignee can be changed as much as needed.
+The idea is that the assignee is responsible for that issue until
+it's reassigned to someone else to take it from there.
+
+> **Tip:**
+if a user is not member of that project, it can only be
+assigned to them if they created the issue themselves.
+
+##### 3.1. Multiple Assignees (EES/EEP)
+
+Issue Weights are only available in [GitLab Enterprise Edition](https://about.gitlab.com/gitlab-ee/).
+
+Often multiple people likely work on the same issue together,
+which can especially be difficult to track in large teams
+where there is shared ownership of an issue.
+
+In GitLab Enterprise Edition, you can also select multiple assignees
+to an issue.
+
+> **Note:**
+Multiple Assignees was [introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/1904)
+in [GitLab Enterprise Edition 9.2](https://about.gitlab.com/2017/05/22/gitlab-9-2-released/#multiple-assignees-for-issues).
+
+#### 4. Milestone
+
+- Select a [milestone](../milestones/index.md) to attribute that issue to.
+
+#### 5. Time Tracking (EES/EEP)
+
+This feature is available only in [GitLab Enterprise Edition](https://about.gitlab.com/gitlab-ee/).
+
+- Estimate time: add an estimate time in which the issue will be implemented
+- Spend: add the time spent on the implementation of that issue
+
+> **Note:**
+both estimate and spend times are set via [GitLab Quick Actions](../quick_actions.md).
+
+Learn more on the [Time Tracking documentation](https://docs.gitlab.com/ee/workflow/time_tracking.html).
+
+#### 6. Due date
+
+When you work on a tight schedule, and it's important to
+have a way to setup a deadline for implementations and for solving
+problems. This can be facilitated by the [due date](due_dates.md)). Due dates
+can be changed as many times as needed.
+
+#### 7. Labels
+
+Categorize issues by giving them [labels](../labels.md). They help to
+organize team's workflows, once they enable you to work with the
+[GitLab Issue Board](index.md#gitlab-issue-board).
+
+Group Labels, which allow you to use the same labels per
+group of projects, can be also given to issues. They work exactly the same,
+but they are immediately available to all projects in the group.
+
+> **Tip:**
+if the label doesn't exist yet, when you click **Edit**, it opens a dropdown menu from which you can select **Create new label**.
+
+#### 8. Weight (EES/EEP)
+
+Issue Weights are only available in [GitLab Enterprise Edition](https://about.gitlab.com/gitlab-ee/).
+
+- Attribute a weight (in a 0 to 9 range) to that issue. Easy to complete
+should weight 1 and very hard to complete should weight 9.
+
+Learn more on the [Issue Weight documentation](https://docs.gitlab.com/ee/workflow/issue_weight.html).
+
+#### 9. Participants
+
+- People involved in that issue (mentioned in the description or in the [discussion](../../discussions/index.md)).
+
+#### 10. Notifications
+
+- Subscribe: if you are not a participant of the discussion on that issue, but
+want to receive notifications on each new input, subscribe to it.
+- Unsubscribe: if you are receiving notifications on that issue but no
+longer want to receive them, unsubscribe to it.
+
+Read more on the [notifications documentation](../../../workflow/notifications.md#issue-merge-request-events).
+
+#### 11. Reference
+
+- A quick "copy to clipboard" button to that issue's reference, `foo/bar#xxx`, where `foo` is the `username` or `groupname`, `bar`
+is the `project-name`, and `xxx` is the issue number.
+
+#### 12. Title and description
+
+- Title: a plain text title describing the issue's subject.
+- Description: a text field which fully supports [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm).
+
+#### 13. @mentions
+
+- Mentions: you can either `@mention` a user or a group present in your
+GitLab instance and they will be notified via todos and email, unless that
+person has disabled all notifications in their profile settings.
+
+To change your [notification settings](../../../workflow/notifications.md) navigate to
+**Profile Settings** > **Notifications** > **Global notification level**
+and choose your preferences from the dropdown menu.
+
+> **Tip:**
+Avoid mentioning `@all` in issues and merge requests,
+as it sends an email notification
+to all the members of that project's group, which can be
+interpreted as spam.
+
+#### 14. Related Merge Requests
+
+- Any merge requests mentioned in that issue's description
+or in the issue thread.
+
+#### 15. Award emoji
+
+- Award an emoji to that issue.
+
+> **Tip:**
+Posting "+1" as comments in threads spam all
+participants of that issue. Awarding an emoji is a way to let them
+know you like it without spamming them.
+
+#### 16. Thread
+
+- Comments: collaborate to that issue by posting comments in its thread.
+These text fields also fully support
+[GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm).
+
+#### 17. Comment, start a discusion, or comment and close
+
+Once you wrote your comment, you can either:
+
+- Click "Comment" and your comment will be published.
+- Click "Start discussion": start a thread within that issue's thread to discuss specific points.
+- Click "Comment and close issue": post your comment and close that issue in one click.
+
+#### 18. New Merge Request
+
+- Create a new merge request (with a new source branch named after the issue) in one action.
+The merge request will automatically close that issue as soon as merged.
+- Optionally, you can just create a [new branch](../repository/web_editor.md#create-a-new-branch-from-an-issue)
+named after that issue.
diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md
index cf1d9cbe69c..8ec7adad172 100644
--- a/doc/user/project/labels.md
+++ b/doc/user/project/labels.md
@@ -65,7 +65,7 @@ issues and merge requests assigned to each label.
> https://gitlab.com/gitlab-org/gitlab-ce/issues/18554.
Prioritized labels are like any other label, but sorted by priority. This allows
-you to sort issues and merge requests by priority.
+you to sort issues and merge requests by label priority.
To prioritize labels, navigate to your project's **Issues > Labels** and click
on the star icon next to them to put them in the priority list. Click on the
@@ -77,9 +77,13 @@ having their priority set to null.
![Prioritize labels](img/labels_prioritize.png)
-Now that you have labels prioritized, you can use the 'Priority' filter in the
-issues or merge requests tracker. Those with the highest priority label, will
-appear on top.
+Now that you have labels prioritized, you can use the 'Priority' and 'Label
+priority' filters in the issues or merge requests tracker.
+
+The 'Label priority' filter puts issues with the highest priority label on top.
+
+The 'Priority' filter sorts issues by their soonest milestone due date, then by
+label priority.
![Filter labels by priority](img/labels_filter_by_priority.png)
@@ -156,4 +160,3 @@ mouse over the label in the issue tracker or wherever else the label is
rendered.
![Label tooltips](img/labels_description_tooltip.png)
-
diff --git a/doc/user/project/merge_requests.md b/doc/user/project/merge_requests.md
index 5af9a5d049c..84a79f04094 100644
--- a/doc/user/project/merge_requests.md
+++ b/doc/user/project/merge_requests.md
@@ -1,169 +1 @@
-# Merge Requests
-
-Merge requests allow you to exchange changes you made to source code and
-collaborate with other people on the same project.
-
-## Authorization for merge requests
-
-There are two main ways to have a merge request flow with GitLab:
-
-1. Working with [protected branches][] in a single repository
-1. Working with forks of an authoritative project
-
-[Learn more about the authorization for merge requests.](merge_requests/authorization_for_merge_requests.md)
-
-## Cherry-pick changes
-
-Cherry-pick any commit in the UI by simply clicking the **Cherry-pick** button
-in a merged merge requests or a commit.
-
-[Learn more about cherry-picking changes.](merge_requests/cherry_pick_changes.md)
-
-## Merge when build succeeds
-
-When reviewing a merge request that looks ready to merge but still has one or
-more CI builds running, you can set it to be merged automatically when all
-builds succeed. This way, you don't have to wait for the builds to finish and
-remember to merge the request manually.
-
-[Learn more about merging when build succeeds.](merge_requests/merge_when_build_succeeds.md)
-
-## Resolve discussion comments in merge requests reviews
-
-Keep track of the progress during a code review with resolving comments.
-Resolving comments prevents you from forgetting to address feedback and lets
-you hide discussions that are no longer relevant.
-
-[Read more about resolving discussion comments in merge requests reviews.](merge_requests/merge_request_discussion_resolution.md)
-
-## Resolve conflicts
-
-When a merge request has conflicts, GitLab may provide the option to resolve
-those conflicts in the GitLab UI.
-
-[Learn more about resolving merge conflicts in the UI.](merge_requests/resolve_conflicts.md)
-
-## Revert changes
-
-GitLab implements Git's powerful feature to revert any commit with introducing
-a **Revert** button in merge requests and commit details.
-
-[Learn more about reverting changes in the UI](merge_requests/revert_changes.md)
-
-## Merge requests versions
-
-Every time you push to a branch that is tied to a merge request, a new version
-of merge request diff is created. When you visit a merge request that contains
-more than one pushes, you can select and compare the versions of those merge
-request diffs.
-
-[Read more about the merge requests versions.](merge_requests/versions.md)
-
-## Work In Progress merge requests
-
-To prevent merge requests from accidentally being accepted before they're
-completely ready, GitLab blocks the "Accept" button for merge requests that
-have been marked as a **Work In Progress**.
-
-[Learn more about settings a merge request as "Work In Progress".](merge_requests/work_in_progress_merge_requests.md)
-
-## Ignore whitespace changes in Merge Request diff view
-
-If you click the **Hide whitespace changes** button, you can see the diff
-without whitespace changes (if there are any). This is also working when on a
-specific commit page.
-
-![MR diff](merge_requests/img/merge_request_diff.png)
-
->**Tip:**
-You can append `?w=1` while on the diffs page of a merge request to ignore any
-whitespace changes.
-
-## Tips
-
-Here are some tips that will help you be more efficient with merge requests in
-the command line.
-
-> **Note:**
-This section might move in its own document in the future.
-
-### Checkout merge requests locally
-
-A merge request contains all the history from a repository, plus the additional
-commits added to the branch associated with the merge request. Here's a few
-tricks to checkout a merge request locally.
-
-Please note that you can checkout a merge request locally even if the source
-project is a fork (even a private fork) of the target project.
-
-#### Checkout locally by adding a git alias
-
-Add the following alias to your `~/.gitconfig`:
-
-```
-[alias]
- mr = !sh -c 'git fetch $1 merge-requests/$2/head:mr-$1-$2 && git checkout mr-$1-$2' -
-```
-
-Now you can check out a particular merge request from any repository and any
-remote. For example, to check out the merge request with ID 5 as shown in GitLab
-from the `upstream` remote, do:
-
-```
-git mr upstream 5
-```
-
-This will fetch the merge request into a local `mr-upstream-5` branch and check
-it out.
-
-#### Checkout locally by modifying `.git/config` for a given repository
-
-Locate the section for your GitLab remote in the `.git/config` file. It looks
-like this:
-
-```
-[remote "origin"]
- url = https://gitlab.com/gitlab-org/gitlab-ce.git
- fetch = +refs/heads/*:refs/remotes/origin/*
-```
-
-You can open the file with:
-
-```
-git config -e
-```
-
-Now add the following line to the above section:
-
-```
-fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*
-```
-
-In the end, it should look like this:
-
-```
-[remote "origin"]
- url = https://gitlab.com/gitlab-org/gitlab-ce.git
- fetch = +refs/heads/*:refs/remotes/origin/*
- fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*
-```
-
-Now you can fetch all the merge requests:
-
-```
-git fetch origin
-
-...
-From https://gitlab.com/gitlab-org/gitlab-ce.git
- * [new ref] refs/merge-requests/1/head -> origin/merge-requests/1
- * [new ref] refs/merge-requests/2/head -> origin/merge-requests/2
-...
-```
-
-And to check out a particular merge request:
-
-```
-git checkout origin/merge-requests/1
-```
-
-[protected branches]: protected_branches.md
+This document was moved to [merge_requests/index.md](merge_requests/index.md).
diff --git a/doc/user/project/merge_requests/img/cherry_pick_changes_commit.png b/doc/user/project/merge_requests/img/cherry_pick_changes_commit.png
index 7fb68cc9e9b..5ab094ab367 100644
--- a/doc/user/project/merge_requests/img/cherry_pick_changes_commit.png
+++ b/doc/user/project/merge_requests/img/cherry_pick_changes_commit.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/cherry_pick_changes_commit_modal.png b/doc/user/project/merge_requests/img/cherry_pick_changes_commit_modal.png
index 5267e04562f..42dcb9203ec 100644
--- a/doc/user/project/merge_requests/img/cherry_pick_changes_commit_modal.png
+++ b/doc/user/project/merge_requests/img/cherry_pick_changes_commit_modal.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/cherry_pick_changes_mr.png b/doc/user/project/merge_requests/img/cherry_pick_changes_mr.png
index 975fb13e463..71227747182 100644
--- a/doc/user/project/merge_requests/img/cherry_pick_changes_mr.png
+++ b/doc/user/project/merge_requests/img/cherry_pick_changes_mr.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/cherry_pick_changes_mr_modal.png b/doc/user/project/merge_requests/img/cherry_pick_changes_mr_modal.png
index 6c003bacbe3..604eb22f51c 100644
--- a/doc/user/project/merge_requests/img/cherry_pick_changes_mr_modal.png
+++ b/doc/user/project/merge_requests/img/cherry_pick_changes_mr_modal.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/commit_compare.png b/doc/user/project/merge_requests/img/commit_compare.png
index 0e4a2b23c04..e612a39716e 100644
--- a/doc/user/project/merge_requests/img/commit_compare.png
+++ b/doc/user/project/merge_requests/img/commit_compare.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/conflict_section.png b/doc/user/project/merge_requests/img/conflict_section.png
index 842e50b14b2..cfc17013218 100644
--- a/doc/user/project/merge_requests/img/conflict_section.png
+++ b/doc/user/project/merge_requests/img/conflict_section.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/discussion_view.png b/doc/user/project/merge_requests/img/discussion_view.png
deleted file mode 100644
index 83bb60acce2..00000000000
--- a/doc/user/project/merge_requests/img/discussion_view.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/discussions_resolved.png b/doc/user/project/merge_requests/img/discussions_resolved.png
deleted file mode 100644
index 85428129ac8..00000000000
--- a/doc/user/project/merge_requests/img/discussions_resolved.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_conflict_editor.png b/doc/user/project/merge_requests/img/merge_conflict_editor.png
new file mode 100644
index 00000000000..6660920c191
--- /dev/null
+++ b/doc/user/project/merge_requests/img/merge_conflict_editor.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_request_diff.png b/doc/user/project/merge_requests/img/merge_request_diff.png
index 06ee4908edc..9c5488cb207 100644
--- a/doc/user/project/merge_requests/img/merge_request_diff.png
+++ b/doc/user/project/merge_requests/img/merge_request_diff.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_request_widget.png b/doc/user/project/merge_requests/img/merge_request_widget.png
index ffb96b17b07..43a945c74d9 100644
--- a/doc/user/project/merge_requests/img/merge_request_widget.png
+++ b/doc/user/project/merge_requests/img/merge_request_widget.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_when_build_succeeds_enable.png b/doc/user/project/merge_requests/img/merge_when_build_succeeds_enable.png
deleted file mode 100644
index b86e6d7b3fd..00000000000
--- a/doc/user/project/merge_requests/img/merge_when_build_succeeds_enable.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_when_build_succeeds_only_if_succeeds_msg.png b/doc/user/project/merge_requests/img/merge_when_build_succeeds_only_if_succeeds_msg.png
deleted file mode 100644
index 6b9756b7418..00000000000
--- a/doc/user/project/merge_requests/img/merge_when_build_succeeds_only_if_succeeds_msg.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_when_build_succeeds_only_if_succeeds_settings.png b/doc/user/project/merge_requests/img/merge_when_build_succeeds_only_if_succeeds_settings.png
deleted file mode 100644
index 18bebf5fe92..00000000000
--- a/doc/user/project/merge_requests/img/merge_when_build_succeeds_only_if_succeeds_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_when_build_succeeds_status.png b/doc/user/project/merge_requests/img/merge_when_build_succeeds_status.png
deleted file mode 100644
index f3ea61d8147..00000000000
--- a/doc/user/project/merge_requests/img/merge_when_build_succeeds_status.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_enable.png b/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_enable.png
new file mode 100644
index 00000000000..33f5a4a7a02
--- /dev/null
+++ b/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_enable.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_msg.png b/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_msg.png
new file mode 100644
index 00000000000..c43f76b058c
--- /dev/null
+++ b/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_msg.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_settings.png b/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_settings.png
new file mode 100644
index 00000000000..9629ed99838
--- /dev/null
+++ b/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_settings.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_status.png b/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_status.png
new file mode 100644
index 00000000000..d0691437c65
--- /dev/null
+++ b/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_status.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/resolve_comment_button.png b/doc/user/project/merge_requests/img/resolve_comment_button.png
deleted file mode 100644
index 2c4ab2f5d53..00000000000
--- a/doc/user/project/merge_requests/img/resolve_comment_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/resolve_discussion_button.png b/doc/user/project/merge_requests/img/resolve_discussion_button.png
deleted file mode 100644
index 73f265bb101..00000000000
--- a/doc/user/project/merge_requests/img/resolve_discussion_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/revert_changes_commit.png b/doc/user/project/merge_requests/img/revert_changes_commit.png
index e7194fc3504..a0663e130e9 100644
--- a/doc/user/project/merge_requests/img/revert_changes_commit.png
+++ b/doc/user/project/merge_requests/img/revert_changes_commit.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/revert_changes_commit_modal.png b/doc/user/project/merge_requests/img/revert_changes_commit_modal.png
index c660ec7eaec..ef7b6dae553 100644
--- a/doc/user/project/merge_requests/img/revert_changes_commit_modal.png
+++ b/doc/user/project/merge_requests/img/revert_changes_commit_modal.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/revert_changes_mr.png b/doc/user/project/merge_requests/img/revert_changes_mr.png
index 3002f0ac1c5..8792018ee53 100644
--- a/doc/user/project/merge_requests/img/revert_changes_mr.png
+++ b/doc/user/project/merge_requests/img/revert_changes_mr.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/revert_changes_mr_modal.png b/doc/user/project/merge_requests/img/revert_changes_mr_modal.png
index c6aaeecc8a6..f6540c9dd33 100644
--- a/doc/user/project/merge_requests/img/revert_changes_mr_modal.png
+++ b/doc/user/project/merge_requests/img/revert_changes_mr_modal.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/versions-compare.png b/doc/user/project/merge_requests/img/versions-compare.png
deleted file mode 100644
index 890cae7768c..00000000000
--- a/doc/user/project/merge_requests/img/versions-compare.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/versions-dropdown.png b/doc/user/project/merge_requests/img/versions-dropdown.png
deleted file mode 100644
index 9bab9304e14..00000000000
--- a/doc/user/project/merge_requests/img/versions-dropdown.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/versions.png b/doc/user/project/merge_requests/img/versions.png
index 6c86f2c68ac..33c58d2abff 100644
--- a/doc/user/project/merge_requests/img/versions.png
+++ b/doc/user/project/merge_requests/img/versions.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/versions_compare.png b/doc/user/project/merge_requests/img/versions_compare.png
new file mode 100644
index 00000000000..db978ea7b1d
--- /dev/null
+++ b/doc/user/project/merge_requests/img/versions_compare.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/versions_dropdown.png b/doc/user/project/merge_requests/img/versions_dropdown.png
new file mode 100644
index 00000000000..889a2d93e6c
--- /dev/null
+++ b/doc/user/project/merge_requests/img/versions_dropdown.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/versions_system_note.png b/doc/user/project/merge_requests/img/versions_system_note.png
new file mode 100644
index 00000000000..90be6298d15
--- /dev/null
+++ b/doc/user/project/merge_requests/img/versions_system_note.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/wip_blocked_accept_button.png b/doc/user/project/merge_requests/img/wip_blocked_accept_button.png
index 89c458aa8d9..047b0b4620f 100644
--- a/doc/user/project/merge_requests/img/wip_blocked_accept_button.png
+++ b/doc/user/project/merge_requests/img/wip_blocked_accept_button.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/wip_mark_as_wip.png b/doc/user/project/merge_requests/img/wip_mark_as_wip.png
index 9c37354a653..8bd206bc24a 100644
--- a/doc/user/project/merge_requests/img/wip_mark_as_wip.png
+++ b/doc/user/project/merge_requests/img/wip_mark_as_wip.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/wip_unmark_as_wip.png b/doc/user/project/merge_requests/img/wip_unmark_as_wip.png
index 31f7326beb0..c0bfa6a35a2 100644
--- a/doc/user/project/merge_requests/img/wip_unmark_as_wip.png
+++ b/doc/user/project/merge_requests/img/wip_unmark_as_wip.png
Binary files differ
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
new file mode 100644
index 00000000000..954454f7e7a
--- /dev/null
+++ b/doc/user/project/merge_requests/index.md
@@ -0,0 +1,169 @@
+# Merge requests
+
+Merge requests allow you to exchange changes you made to source code and
+collaborate with other people on the same project.
+
+## Authorization for merge requests
+
+There are two main ways to have a merge request flow with GitLab:
+
+1. Working with [protected branches][] in a single repository
+1. Working with forks of an authoritative project
+
+[Learn more about the authorization for merge requests.](authorization_for_merge_requests.md)
+
+## Cherry-pick changes
+
+Cherry-pick any commit in the UI by simply clicking the **Cherry-pick** button
+in a merged merge requests or a commit.
+
+[Learn more about cherry-picking changes.](cherry_pick_changes.md)
+
+## Merge when pipeline succeeds
+
+When reviewing a merge request that looks ready to merge but still has one or
+more CI jobs running, you can set it to be merged automatically when CI
+pipeline succeeds. This way, you don't have to wait for the pipeline to finish
+and remember to merge the request manually.
+
+[Learn more about merging when pipeline succeeds.](merge_when_pipeline_succeeds.md)
+
+## Resolve discussion comments in merge requests reviews
+
+Keep track of the progress during a code review with resolving comments.
+Resolving comments prevents you from forgetting to address feedback and lets
+you hide discussions that are no longer relevant.
+
+[Read more about resolving discussion comments in merge requests reviews.](../../discussions/index.md)
+
+## Resolve conflicts
+
+When a merge request has conflicts, GitLab may provide the option to resolve
+those conflicts in the GitLab UI.
+
+[Learn more about resolving merge conflicts in the UI.](resolve_conflicts.md)
+
+## Revert changes
+
+GitLab implements Git's powerful feature to revert any commit with introducing
+a **Revert** button in merge requests and commit details.
+
+[Learn more about reverting changes in the UI](revert_changes.md)
+
+## Merge requests versions
+
+Every time you push to a branch that is tied to a merge request, a new version
+of merge request diff is created. When you visit a merge request that contains
+more than one pushes, you can select and compare the versions of those merge
+request diffs.
+
+[Read more about the merge requests versions.](versions.md)
+
+## Work In Progress merge requests
+
+To prevent merge requests from accidentally being accepted before they're
+completely ready, GitLab blocks the "Accept" button for merge requests that
+have been marked as a **Work In Progress**.
+
+[Learn more about settings a merge request as "Work In Progress".](work_in_progress_merge_requests.md)
+
+## Ignore whitespace changes in Merge Request diff view
+
+If you click the **Hide whitespace changes** button, you can see the diff
+without whitespace changes (if there are any). This is also working when on a
+specific commit page.
+
+![MR diff](img/merge_request_diff.png)
+
+>**Tip:**
+You can append `?w=1` while on the diffs page of a merge request to ignore any
+whitespace changes.
+
+## Tips
+
+Here are some tips that will help you be more efficient with merge requests in
+the command line.
+
+> **Note:**
+This section might move in its own document in the future.
+
+### Checkout merge requests locally
+
+A merge request contains all the history from a repository, plus the additional
+commits added to the branch associated with the merge request. Here's a few
+tricks to checkout a merge request locally.
+
+Please note that you can checkout a merge request locally even if the source
+project is a fork (even a private fork) of the target project.
+
+#### Checkout locally by adding a git alias
+
+Add the following alias to your `~/.gitconfig`:
+
+```
+[alias]
+ mr = !sh -c 'git fetch $1 merge-requests/$2/head:mr-$1-$2 && git checkout mr-$1-$2' -
+```
+
+Now you can check out a particular merge request from any repository and any
+remote. For example, to check out the merge request with ID 5 as shown in GitLab
+from the `upstream` remote, do:
+
+```
+git mr upstream 5
+```
+
+This will fetch the merge request into a local `mr-upstream-5` branch and check
+it out.
+
+#### Checkout locally by modifying `.git/config` for a given repository
+
+Locate the section for your GitLab remote in the `.git/config` file. It looks
+like this:
+
+```
+[remote "origin"]
+ url = https://gitlab.com/gitlab-org/gitlab-ce.git
+ fetch = +refs/heads/*:refs/remotes/origin/*
+```
+
+You can open the file with:
+
+```
+git config -e
+```
+
+Now add the following line to the above section:
+
+```
+fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*
+```
+
+In the end, it should look like this:
+
+```
+[remote "origin"]
+ url = https://gitlab.com/gitlab-org/gitlab-ce.git
+ fetch = +refs/heads/*:refs/remotes/origin/*
+ fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*
+```
+
+Now you can fetch all the merge requests:
+
+```
+git fetch origin
+
+...
+From https://gitlab.com/gitlab-org/gitlab-ce.git
+ * [new ref] refs/merge-requests/1/head -> origin/merge-requests/1
+ * [new ref] refs/merge-requests/2/head -> origin/merge-requests/2
+...
+```
+
+And to check out a particular merge request:
+
+```
+git checkout origin/merge-requests/1
+```
+
+[protected branches]: ../protected_branches.md
diff --git a/doc/user/project/merge_requests/merge_request_discussion_resolution.md b/doc/user/project/merge_requests/merge_request_discussion_resolution.md
index 2559f5f5250..200965875a1 100644
--- a/doc/user/project/merge_requests/merge_request_discussion_resolution.md
+++ b/doc/user/project/merge_requests/merge_request_discussion_resolution.md
@@ -1,40 +1 @@
-# Merge Request discussion resolution
-
-> [Introduced][ce-5022] in GitLab 8.11.
-
-Discussion resolution helps keep track of progress during code review.
-Resolving comments prevents you from forgetting to address feedback and lets you
-hide discussions that are no longer relevant.
-
-!["A discussion between two people on a piece of code"][discussion-view]
-
-Comments and discussions can be resolved by anyone with at least Developer
-access to the project, as well as by the author of the merge request.
-
-## Marking a comment or discussion as resolved
-
-You can mark a discussion as resolved by clicking the "Resolve discussion"
-button at the bottom of the discussion.
-
-!["Resolve discussion" button][resolve-discussion-button]
-
-Alternatively, you can mark each comment as resolved individually.
-
-!["Resolve comment" button][resolve-comment-button]
-
-## Jumping between unresolved discussions
-
-When a merge request has a large number of comments it can be difficult to track
-what remains unresolved. You can jump between unresolved discussions with the
-Jump button next to the Reply field on a discussion.
-
-You can also jump to the first unresolved discussion from the button next to the
-resolved discussions tracker.
-
-!["3/4 discussions resolved"][discussions-resolved]
-
-[ce-5022]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5022
-[resolve-discussion-button]: img/resolve_discussion_button.png
-[resolve-comment-button]: img/resolve_comment_button.png
-[discussion-view]: img/discussion_view.png
-[discussions-resolved]: img/discussions_resolved.png
+This document was moved to [another location](../../discussions/index.md).
diff --git a/doc/user/project/merge_requests/merge_when_build_succeeds.md b/doc/user/project/merge_requests/merge_when_build_succeeds.md
index 011f9cbc381..2167fdfbf7e 100644
--- a/doc/user/project/merge_requests/merge_when_build_succeeds.md
+++ b/doc/user/project/merge_requests/merge_when_build_succeeds.md
@@ -1,46 +1,5 @@
-# Merge When Build Succeeds
+This document was moved to [merge_when_pipeline_succeeds](merge_when_pipeline_succeeds.md).
-When reviewing a merge request that looks ready to merge but still has one or
-more CI builds running, you can set it to be merged automatically when all
-builds succeed. This way, you don't have to wait for the builds to finish and
-remember to merge the request manually.
+>[Introduced][ce-7135] by the "Rename MWBS service to Merge When Pipeline Succeeds" change.
-![Enable](img/merge_when_build_succeeds_enable.png)
-
-When you hit the "Merge When Build Succeeds" button, the status of the merge
-request will be updated to represent the impending merge. If you cannot wait
-for the build to succeed and want to merge immediately, this option is available
-in the dropdown menu on the right of the main button.
-
-Both team developers and the author of the merge request have the option to
-cancel the automatic merge if they find a reason why it shouldn't be merged
-after all.
-
-![Status](img/merge_when_build_succeeds_status.png)
-
-When the build succeeds, the merge request will automatically be merged. When
-the build fails, the author gets a chance to retry any failed builds, or to
-push new commits to fix the failure.
-
-When the builds are retried and succeed on the second try, the merge request
-will automatically be merged after all. When the merge request is updated with
-new commits, the automatic merge is automatically canceled to allow the new
-changes to be reviewed.
-
-## Only allow merge requests to be merged if the build succeeds
-
-> **Note:**
-You need to have builds configured to enable this feature.
-
-You can prevent merge requests from being merged if their build did not succeed.
-
-Navigate to your project's settings page, select the
-**Only allow merge requests to be merged if the build succeeds** check box and
-hit **Save** for the changes to take effect.
-
-![Only allow merge if build succeeds settings](img/merge_when_build_succeeds_only_if_succeeds_settings.png)
-
-From now on, every time the build fails you will not be able to merge the merge
-request from the UI, until you make the build pass.
-
-![Only allow merge if build succeeds msg](img/merge_when_build_succeeds_only_if_succeeds_msg.png)
+[ce-7135]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7135
diff --git a/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md b/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
new file mode 100644
index 00000000000..bdd7d0022e6
--- /dev/null
+++ b/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
@@ -0,0 +1,47 @@
+# Merge When Pipeline Succeeds
+
+When reviewing a merge request that looks ready to merge but still has one or
+more CI jobs running, you can set it to be merged automatically when the
+jobs pipeline succeeds. This way, you don't have to wait for the jobs to
+finish and remember to merge the request manually.
+
+![Enable](img/merge_when_pipeline_succeeds_enable.png)
+
+When you hit the "Merge When Pipeline Succeeds" button, the status of the merge
+request will be updated to represent the impending merge. If you cannot wait
+for the pipeline to succeed and want to merge immediately, this option is
+available in the dropdown menu on the right of the main button.
+
+Both team developers and the author of the merge request have the option to
+cancel the automatic merge if they find a reason why it shouldn't be merged
+after all.
+
+![Status](img/merge_when_pipeline_succeeds_status.png)
+
+When the pipeline succeeds, the merge request will automatically be merged.
+When the pipeline fails, the author gets a chance to retry any failed jobs,
+or to push new commits to fix the failure.
+
+When the jobs are retried and succeed on the second try, the merge request
+will automatically be merged after all. When the merge request is updated with
+new commits, the automatic merge is automatically canceled to allow the new
+changes to be reviewed.
+
+## Only allow merge requests to be merged if the pipeline succeeds
+
+> **Note:**
+You need to have jobs configured to enable this feature.
+
+You can prevent merge requests from being merged if their pipeline did not succeed
+or if there are discussions to be resolved.
+
+Navigate to your project's settings page, select the
+**Only allow merge requests to be merged if the pipeline succeeds** check box and
+hit **Save** for the changes to take effect.
+
+![Only allow merge if pipeline succeeds settings](img/merge_when_pipeline_succeeds_only_if_succeeds_settings.png)
+
+From now on, every time the pipeline fails you will not be able to merge the
+merge request from the UI, until you make all relevant jobs pass.
+
+![Only allow merge if pipeline succeeds message](img/merge_when_pipeline_succeeds_only_if_succeeds_msg.png)
diff --git a/doc/user/project/merge_requests/resolve_conflicts.md b/doc/user/project/merge_requests/resolve_conflicts.md
index 4d7225bd820..68c49054e47 100644
--- a/doc/user/project/merge_requests/resolve_conflicts.md
+++ b/doc/user/project/merge_requests/resolve_conflicts.md
@@ -21,6 +21,18 @@ request into the source branch, resolving the conflicts using the options
chosen. If the source branch is `feature` and the target branch is `master`,
this is similar to performing `git checkout feature; git merge master` locally.
+## Merge conflict editor
+
+> Introduced in GitLab 8.13.
+
+The merge conflict resolution editor allows for more complex merge conflicts,
+which require the user to manually modify a file in order to resolve a conflict,
+to be solved right form the GitLab interface. Use the **Edit inline** button
+to open the editor. Once you're sure about your changes, hit the
+**Commit conflict resolution** button.
+
+![Merge conflict editor](img/merge_conflict_editor.png)
+
## Conflicts available for resolution
GitLab allows resolving conflicts in a file where all of the below are true:
diff --git a/doc/user/project/merge_requests/versions.md b/doc/user/project/merge_requests/versions.md
index 2805fdf635c..610250ccf12 100644
--- a/doc/user/project/merge_requests/versions.md
+++ b/doc/user/project/merge_requests/versions.md
@@ -1,32 +1,39 @@
# Merge requests versions
-> Will be [introduced][ce-5467] in GitLab 8.12.
+>**Notes:**
+- [Introduced][ce-5467] in GitLab 8.12.
+- Comments are disabled while viewing outdated merge versions or comparing to
+ versions other than base.
+- Merge request versions are based on push not on commit. So, if you pushed 5
+ commits in a single push, it will be a single option in the dropdown. If you
+ pushed 5 times, that will count for 5 options.
Every time you push to a branch that is tied to a merge request, a new version
of merge request diff is created. When you visit a merge request that contains
more than one pushes, you can select and compare the versions of those merge
request diffs.
-![Merge Request Versions](img/versions.png)
+![Merge request versions](img/versions.png)
+
+---
By default, the latest version of changes is shown. However, you
can select an older one from version dropdown.
-![Merge Request Versions](img/versions-dropdown.png)
+![Merge request versions dropdown](img/versions_dropdown.png)
-You can also compare the merge request version with older one to see what is
-changed since then.
+---
-![Merge Request Versions](img/versions-compare.png)
+You can also compare the merge request version with an older one to see what has
+changed since then.
-Please note that comments are disabled while viewing outdated merge versions
-or comparing to versions other than base.
+![Merge request versions compare](img/versions_compare.png)
---
->**Note:**
-Merge request versions are based on push not on commit. So, if you pushed 5
-commits in a single push, it will be a single option in the dropdown. If you
-pushed 5 times, that will count for 5 options.
+Every time you push new changes to the branch, a link to compare the last
+changes appears as a system note.
+
+![Merge request versions system note](img/versions_system_note.png)
[ce-5467]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5467
diff --git a/doc/user/project/milestones/img/milestone_create.png b/doc/user/project/milestones/img/milestone_create.png
new file mode 100644
index 00000000000..beb2caa897f
--- /dev/null
+++ b/doc/user/project/milestones/img/milestone_create.png
Binary files differ
diff --git a/doc/user/project/milestones/img/milestone_group_create.png b/doc/user/project/milestones/img/milestone_group_create.png
new file mode 100644
index 00000000000..7aaa7c56c15
--- /dev/null
+++ b/doc/user/project/milestones/img/milestone_group_create.png
Binary files differ
diff --git a/doc/user/project/milestones/img/progress.png b/doc/user/project/milestones/img/progress.png
new file mode 100644
index 00000000000..c85aecca729
--- /dev/null
+++ b/doc/user/project/milestones/img/progress.png
Binary files differ
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
new file mode 100644
index 00000000000..99233ed5ae2
--- /dev/null
+++ b/doc/user/project/milestones/index.md
@@ -0,0 +1,54 @@
+# Milestones
+
+Milestones allow you to organize issues and merge requests into a cohesive group,
+optionally setting a due date. A common use is keeping track of an upcoming
+software version. Milestones can be created per-project or per-group.
+
+## Creating a project milestone
+
+>**Note:**
+You need [Master permissions](../../permissions.md) in order to create a milestone.
+
+You can find the milestones page under your project's **Issues ➔ Milestones**.
+To create a new milestone, simply click the **New milestone** button when in the
+milestones page. A milestone can have a title, a description and start/due dates.
+Once you fill in all the details, hit the **Create milestone** button.
+
+![Creating a milestone](img/milestone_create.png)
+
+## Creating a group milestone
+
+>**Note:**
+You need [Master permissions](../../permissions.md) in order to create a milestone.
+
+You can create a milestone for several projects in the same group simultaneously.
+On the group's **Issues ➔ Milestones** page, you will be able to see the status
+of that milestone across all of the selected projects. To create a new milestone
+for selected projects in the group, click the **New milestone** button. The
+form is the same as when creating a milestone for a specific project with the
+addition of the selection of the projects you want to inherit this milestone.
+
+![Creating a group milestone](img/milestone_group_create.png)
+
+## Special milestone filters
+
+In addition to the milestones that exist in the project or group, there are some
+special options available when filtering by milestone:
+
+* **No Milestone** - only show issues or merge requests without a milestone.
+* **Upcoming** - show issues or merge request that belong to the next open
+ milestone with a due date, by project. (For example: if project A has
+ milestone v1 due in three days, and project B has milestone v2 due in a week,
+ then this will show issues or merge requests from milestone v1 in project A
+ and milestone v2 in project B.)
+* **Started** - show issues or merge requests from any milestone with a start
+ date less than today. Note that this can return results from several
+ milestones in the same project.
+
+## Milestone progress statistics
+
+Milestone statistics can be viewed in the milestone sidebar. The milestone percentage statistic
+is calculated as; closed and merged merge requests plus all closed issues divided by
+total merge requests and issues.
+
+![Milestone statistics](img/progress.png)
diff --git a/doc/user/project/new_ci_build_permissions_model.md b/doc/user/project/new_ci_build_permissions_model.md
index 5253825d507..271adee7da1 100644
--- a/doc/user/project/new_ci_build_permissions_model.md
+++ b/doc/user/project/new_ci_build_permissions_model.md
@@ -1,55 +1,55 @@
-# New CI build permissions model
+# New CI job permissions model
> Introduced in GitLab 8.12.
-GitLab 8.12 has a completely redesigned [build permissions] system. You can find
+GitLab 8.12 has a completely redesigned [job permissions] system. You can find
all discussion and all our concerns when choosing the current approach in issue
[#18994](https://gitlab.com/gitlab-org/gitlab-ce/issues/18994).
---
-Builds permissions should be tightly integrated with the permissions of a user
-who is triggering a build.
+Jobs permissions should be tightly integrated with the permissions of a user
+who is triggering a job.
The reasons to do it like that are:
- We already have a permissions system in place: group and project membership
of users.
-- We already fully know who is triggering a build (using `git push`, using the
+- We already fully know who is triggering a job (using `git push`, using the
web UI, executing triggers).
- We already know what user is allowed to do.
-- We use the user permissions for builds that are triggered by the user.
+- We use the user permissions for jobs that are triggered by the user.
- It opens a lot of possibilities to further enforce user permissions, like
allowing only specific users to access runners or use secure variables and
environments.
-- It is simple and convenient that your build can access everything that you
+- It is simple and convenient that your job can access everything that you
as a user have access to.
-- Short living unique tokens are now used, granting access for time of the build
+- Short living unique tokens are now used, granting access for time of the job
and maximizing security.
-With the new behavior, any build that is triggered by the user, is also marked
+With the new behavior, any job that is triggered by the user, is also marked
with their permissions. When a user does a `git push` or changes files through
the web UI, a new pipeline will be usually created. This pipeline will be marked
-as created be the pusher (local push or via the UI) and any build created in this
+as created be the pusher (local push or via the UI) and any job created in this
pipeline will have the permissions of the pusher.
This allows us to make it really easy to evaluate the access for all projects
-that have Git submodules or are using container images that the pusher would
-have access too. **The permission is granted only for time that build is running.
-The access is revoked after the build is finished.**
+that have [Git submodules][gitsub] or are using container images that the pusher
+would have access too. **The permission is granted only for time that job is
+running. The access is revoked after the job is finished.**
## Types of users
It is important to note that we have a few types of users:
-- **Administrators**: CI builds created by Administrators will not have access
+- **Administrators**: CI jobs created by Administrators will not have access
to all GitLab projects, but only to projects and container images of projects
that the administrator is a member of.That means that if a project is either
public or internal users have access anyway, but if a project is private, the
Administrator will have to be a member of it in order to have access to it
- via another project's build.
+ via another project's job.
-- **External users**: CI builds created by [external users][ext] will have
+- **External users**: CI jobs created by [external users][ext] will have
access only to projects to which user has at least reporter access. This
rules out accessing all internal projects by default,
@@ -57,69 +57,55 @@ This allows us to make the CI and permission system more trustworthy.
Let's consider the following scenario:
1. You are an employee of a company. Your company has a number of internal tools
- hosted in private repositories and you have multiple CI builds that make use
+ hosted in private repositories and you have multiple CI jobs that make use
of these repositories.
-2. You invite a new [external user][ext]. CI builds created by that user do not
+2. You invite a new [external user][ext]. CI jobs created by that user do not
have access to internal repositories, because the user also doesn't have the
access from within GitLab. You as an employee have to grant explicit access
for this user. This allows us to prevent from accidental data leakage.
-## Build token
+## Job token
-A unique build token is generated for each build and it allows the user to
+A unique job token is generated for each job and it allows the user to
access all projects that would be normally accessible to the user creating that
-build.
+job.
We try to make sure that this token doesn't leak by:
-1. Securing all API endpoints to not expose the build token.
-1. Masking the build token from build logs.
-1. Allowing to use the build token **only** when build is running.
+1. Securing all API endpoints to not expose the job token.
+1. Masking the job token from job logs.
+1. Allowing to use the job token **only** when job is running.
However, this brings a question about the Runners security. To make sure that
this token doesn't leak, you should also make sure that you configure
your Runners in the most possible secure way, by avoiding the following:
1. Any usage of Docker's `privileged` mode is risky if the machines are re-used.
-1. Using the `shell` executor since builds run on the same machine.
+1. Using the `shell` executor since jobs run on the same machine.
By using an insecure GitLab Runner configuration, you allow the rogue developers
-to steal the tokens of other builds.
+to steal the tokens of other jobs.
-## Debugging problems
+## Pipeline triggers
-With the new permission model in place, there may be times that your build will
-fail. This is most likely because your project tries to access other project's
-sources, and you don't have the appropriate permissions. In the build log look
-for information about 403 or forbidden access messages
-
-As an Administrator, you can verify that the user is a member of the group or
-project they're trying to have access to, and you can impersonate the user to
-retry the failing build in order to verify that everything is correct.
-
-You need to make sure that your installation has HTTPS cloning enabled.
-HTTPS support is required by GitLab CI to clone all sources.
-
-## Build triggers
-
-[Build triggers][triggers] do not support the new permission model.
-They continue to use the old authentication mechanism where the CI build
-can access only its own sources. We plan to remove that limitation in one of
-the upcoming releases.
+Since 9.0 [pipeline triggers][triggers] do support the new permission model.
+The new triggers do impersonate their associated user including their access
+to projects and their project permissions. To migrate trigger to use new permisison
+model use **Take ownership**.
## Before GitLab 8.12
-In versions before GitLab 8.12, all CI builds would use the CI Runner's token
+In versions before GitLab 8.12, all CI jobs would use the CI Runner's token
to checkout project sources.
The project's Runner's token was a token that you could find under the
-project's **Settings > CI/CD Pipelines** and was limited to access only that
+project's **Settings > Pipelines** and was limited to access only that
project.
It could be used for registering new specific Runners assigned to the project
and to checkout project sources.
It could also be used with the GitLab Container Registry for that project,
-allowing pulling and pushing Docker images from within the CI build.
+allowing pulling and pushing Docker images from within the CI job.
---
@@ -129,17 +115,17 @@ GitLab would create a special checkout URL like:
https://gitlab-ci-token:<project-runners-token>/gitlab.com/gitlab-org/gitlab-ce.git
```
-And then the users could also use it in their CI builds all Docker related
+And then the users could also use it in their CI jobs all Docker related
commands to interact with GitLab Container Registry. For example:
```
-docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.gitlab.com
+docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.gitlab.com
```
Using single token had multiple security implications:
- The token would be readable to anyone who had developer access to a project
- that could run CI builds, allowing the developer to register any specific
+ that could run CI jobs, allowing the developer to register any specific
Runner for that project.
- The token would allow to access only the project's sources, forbidding from
accessing any other projects.
@@ -147,146 +133,111 @@ Using single token had multiple security implications:
for registering specific runners and for accessing a project's container
registry with read-write permissions.
-All the above led to a new permission model for builds that was introduced
+All the above led to a new permission model for jobs that was introduced
with GitLab 8.12.
-## Making use of the new CI build permissions model
+## Making use of the new CI job permissions model
-With the new build permission model, there is now an easy way to access all
+With the new job permissions model, there is now an easy way to access all
dependent source code in a project. That way, we can:
-1. Access a project's Git submodules
+1. Access a project's dependent repositories
+1. Access a project's [Git submodules][gitsub]
1. Access private container images
1. Access project's and submodule LFS objects
-Let's see how that works with Git submodules and private Docker images hosted on
+Below you can see the prerequisites needed to make use of the new permissions
+model and how that works with Git submodules and private Docker images hosted on
the container registry.
-## Git submodules
+### Prerequisites to use the new permissions model
->
-It often happens that while working on one project, you need to use another
-project from within it; perhaps it’s a library that a third party developed or
-you’re developing a project separately and are using it in multiple parent
-projects.
-A common issue arises in these scenarios: you want to be able to treat the two
-projects as separate yet still be able to use one from within the other.
->
-_Excerpt from the [Git website][git-scm] about submodules._
-
-If dealing with submodules, your project will probably have a file named
-`.gitmodules`. And this is how it usually looks like:
-
-```
-[submodule "tools"]
- path = tools
- url = git@gitlab.com/group/tools.git
-```
+With the new permissions model in place, there may be times that your job will
+fail. This is most likely because your project tries to access other project's
+sources, and you don't have the appropriate permissions. In the job log look
+for information about 403 or forbidden access messages.
-> **Note:**
-If you are **not** using GitLab 8.12 or higher, you would need to work your way
-around this issue in order to access the sources of `gitlab.com/group/tools`
-(e.g., use [SSH keys](../ssh_keys/README.md)).
->
-With GitLab 8.12 onward, your permissions are used to evaluate what a CI build
-can access. More information about how this system works can be found in the
-[Build permissions model](../../user/permissions.md#builds-permissions).
+In short here's what you need to do should you encounter any issues.
-To make use of the new changes, you have to update your `.gitmodules` file to
-use a relative URL.
+As an administrator:
-Let's consider the following example:
+- **500 errors**: You will need to update [GitLab Workhorse][workhorse] to at
+ least 0.8.2. This is done automatically for Omnibus installations, you need to
+ [check manually][update-docs] for installations from source.
+- **500 errors**: Check if you have another web proxy sitting in front of NGINX (HAProxy,
+ Apache, etc.). It might be a good idea to let GitLab use the internal NGINX
+ web server and not disable it completely. See [this comment][comment] for an
+ example.
+- **403 errors**: You need to make sure that your installation has [HTTP(S)
+ cloning enabled][https]. HTTP(S) support is now a **requirement** by GitLab CI
+ to clone all sources.
-1. Your project is located at `https://gitlab.com/secret-group/my-project`.
-1. To checkout your sources you usually use an SSH address like
- `git@gitlab.com:secret-group/my-project.git`.
-1. Your project depends on `https://gitlab.com/group/tools`.
-1. You have the `.gitmodules` file with above content.
+As a user:
-Since Git allows the usage of relative URLs for your `.gitmodules` configuration,
-this easily allows you to use HTTP for cloning all your CI builds and SSH
-for all your local checkouts.
+- Make sure you are a member of the group or project you're trying to have
+ access to. As an Administrator, you can verify that by impersonating the user
+ and retry the failing job in order to verify that everything is correct.
-For example, if you change the `url` of your `tools` dependency, from
-`git@gitlab.com/group/tools.git` to `../../group/tools.git`, this will instruct
-Git to automatically deduce the URL that should be used when cloning sources.
-Whether you use HTTP or SSH, Git will use that same channel and it will allow
-to make all your CI builds use HTTPS (because GitLab CI uses HTTPS for cloning
-your sources), and all your local clones will continue using SSH.
+### Dependent repositories
-Given the above explanation, your `.gitmodules` file should eventually look
-like this:
+The [Job environment variable][jobenv] `CI_JOB_TOKEN` can be used to
+authenticate any clones of dependent repositories. For example:
```
-[submodule "tools"]
- path = tools
- url = ../../group/tools.git
+git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/myuser/mydependentrepo
```
-However, you have to explicitly tell GitLab CI to clone your submodules as this
-is not done automatically. You can achieve that by adding a `before_script`
-section to your `.gitlab-ci.yml`:
+It can also be used for system-wide authentication
+(only do this in a docker container, it will overwrite ~/.netrc):
```
-before_script:
- - git submodule update --init --recursive
-
-test:
- script:
- - run-my-tests
+echo -e "machine gitlab.com\nlogin gitlab-ci-token\npassword ${CI_JOB_TOKEN}" > ~/.netrc
```
-This will make GitLab CI initialize (fetch) and update (checkout) all your
-submodules recursively.
+### Git submodules
-In case your environment or your Docker image doesn't have Git installed,
-you have to either ask your Administrator or install the missing dependency
-yourself:
-
-```
-# Debian / Ubuntu
-before_script:
- - apt-get update -y
- - apt-get install -y git-core
- - git submodule update --init --recursive
-
-# CentOS / RedHat
-before_script:
- - yum install git
- - git submodule update --init --recursive
-
-# Alpine
-before_script:
- - apk add -U git
- - git submodule update --init --recursive
-```
+To properly configure submodules with GitLab CI, read the
+[Git submodules documentation][gitsub].
### Container Registry
With the update permission model we also extended the support for accessing
Container Registries for private projects.
-> **Note:**
-As GitLab Runner 1.6 doesn't yet incorporate the introduced changes for
-permissions, this makes the `image:` directive to not work with private projects
-automatically. The manual configuration by an Administrator is required to use
-private images. We plan to remove that limitation in one of the upcoming releases.
-
-Your builds can access all container images that you would normally have access
+> **Notes:**
+- GitLab Runner versions prior to 1.8 don't incorporate the introduced changes
+ for permissions. This makes the `image:` directive to not work with private
+ projects automatically and it needs to be configured manually on Runner's host
+ with a predefined account (for example administrator's personal account with
+ access token created explicitly for this purpose). This issue is resolved with
+ latest changes in GitLab Runner 1.8 which receives GitLab credentials with
+ build data.
+- Starting from GitLab 8.12, if you have [2FA] enabled in your account, you need
+ to pass a [personal access token][pat] instead of your password in order to
+ login to GitLab's Container Registry.
+
+Your jobs can access all container images that you would normally have access
to. The only implication is that you can push to the Container Registry of the
-project for which the build is triggered.
+project for which the job is triggered.
This is how an example usage can look like:
```
test:
script:
- - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
+ - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- docker pull $CI_REGISTRY/group/other-project:latest
- docker run $CI_REGISTRY/group/other-project:latest
```
-[git-scm]: https://git-scm.com/book/en/v2/Git-Tools-Submodules
-[build permissions]: ../permissions.md#builds-permissions
+[job permissions]: ../permissions.md#jobs-permissions
+[comment]: https://gitlab.com/gitlab-org/gitlab-ce/issues/22484#note_16648302
[ext]: ../permissions.md#external-users
+[gitsub]: ../../ci/git_submodules.md
+[https]: ../admin_area/settings/visibility_and_access_controls.md#enabled-git-access-protocols
[triggers]: ../../ci/triggers/README.md
+[update-docs]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update
+[workhorse]: https://gitlab.com/gitlab-org/gitlab-workhorse
+[jobenv]: ../../ci/variables/README.md#predefined-variables-environment-variables
+[2fa]: ../profile/account/two_factor_authentication.md
+[pat]: ../profile/personal_access_tokens.md
diff --git a/doc/user/project/pages/getting_started_part_four.md b/doc/user/project/pages/getting_started_part_four.md
new file mode 100644
index 00000000000..bd0cb437924
--- /dev/null
+++ b/doc/user/project/pages/getting_started_part_four.md
@@ -0,0 +1,390 @@
+# GitLab Pages from A to Z: Part 4
+
+> **Article [Type](../../../development/writing_documentation.html#types-of-technical-articles)**: user guide ||
+> **Level**: intermediate ||
+> **Author**: [Marcia Ramos](https://gitlab.com/marcia) ||
+> **Publication date:** 2017/02/22
+
+- [Part 1: Static sites and GitLab Pages domains](getting_started_part_one.md)
+- [Part 2: Quick start guide - Setting up GitLab Pages](getting_started_part_two.md)
+- [Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](getting_started_part_three.md)
+- **Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages**
+
+## Creating and Tweaking `.gitlab-ci.yml` for GitLab Pages
+
+[GitLab CI](https://about.gitlab.com/gitlab-ci/) serves
+numerous purposes, to build, test, and deploy your app
+from GitLab through
+[Continuous Integration, Continuous Delivery, and Continuous Deployment](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/)
+methods. You will need it to build your website with GitLab Pages,
+and deploy it to the Pages server.
+
+What this file actually does is telling the
+[GitLab Runner](https://docs.gitlab.com/runner/) to run scripts
+as you would do from the command line. The Runner acts as your
+terminal. GitLab CI tells the Runner which commands to run.
+Both are built-in in GitLab, and you don't need to set up
+anything for them to work.
+
+Explaining [every detail of GitLab CI](https://docs.gitlab.com/ce/ci/yaml/README.html)
+and GitLab Runner is out of the scope of this guide, but we'll
+need to understand just a few things to be able to write our own
+`.gitlab-ci.yml` or tweak an existing one. It's an
+[Yaml](http://docs.ansible.com/ansible/YAMLSyntax.html) file,
+with its own syntax. You can always check your CI syntax with
+the [GitLab CI Lint Tool](https://gitlab.com/ci/lint).
+
+**Practical Example:**
+
+Let's consider you have a [Jekyll](https://jekyllrb.com/) site.
+To build it locally, you would open your terminal, and run `jekyll build`.
+Of course, before building it, you had to install Jekyll in your computer.
+For that, you had to open your terminal and run `gem install jekyll`.
+Right? GitLab CI + GitLab Runner do the same thing. But you need to
+write in the `.gitlab-ci.yml` the script you want to run so
+GitLab Runner will do it for you. It looks more complicated then it
+is. What you need to tell the Runner:
+
+```
+$ gem install jekyll
+$ jekyll build
+```
+
+### Script
+
+To transpose this script to Yaml, it would be like this:
+
+```yaml
+script:
+ - gem install jekyll
+ - jekyll build
+```
+
+### Job
+
+So far so good. Now, each `script`, in GitLab is organized by
+a `job`, which is a bunch of scripts and settings you want to
+apply to that specific task.
+
+```yaml
+job:
+ script:
+ - gem install jekyll
+ - jekyll build
+```
+
+For GitLab Pages, this `job` has a specific name, called `pages`,
+which tells the Runner you want that task to deploy your website
+with GitLab Pages:
+
+```yaml
+pages:
+ script:
+ - gem install jekyll
+ - jekyll build
+```
+
+### The `public` directory
+
+We also need to tell Jekyll where do you want the website to build,
+and GitLab Pages will only consider files in a directory called `public`.
+To do that with Jekyll, we need to add a flag specifying the
+[destination (`-d`)](https://jekyllrb.com/docs/usage/) of the
+built website: `jekyll build -d public`. Of course, we need
+to tell this to our Runner:
+
+```yaml
+pages:
+ script:
+ - gem install jekyll
+ - jekyll build -d public
+```
+
+### Artifacts
+
+We also need to tell the Runner that this _job_ generates
+_artifacts_, which is the site built by Jekyll.
+Where are these artifacts stored? In the `public` directory:
+
+```yaml
+pages:
+ script:
+ - gem install jekyll
+ - jekyll build -d public
+ artifacts:
+ paths:
+ - public
+```
+
+The script above would be enough to build your Jekyll
+site with GitLab Pages. But, from Jekyll 3.4.0 on, its default
+template originated by `jekyll new project` requires
+[Bundler](http://bundler.io/) to install Jekyll dependencies
+and the default theme. To adjust our script to meet these new
+requirements, we only need to install and build Jekyll with Bundler:
+
+```yaml
+pages:
+ script:
+ - bundle install
+ - bundle exec jekyll build -d public
+ artifacts:
+ paths:
+ - public
+```
+
+That's it! A `.gitlab-ci.yml` with the content above would deploy
+your Jekyll 3.4.0 site with GitLab Pages. This is the minimum
+configuration for our example. On the steps below, we'll refine
+the script by adding extra options to our GitLab CI.
+
+Artifacts will be automatically deleted once GitLab Pages got deployed.
+You can preserve artifacts for limited time by specifying the expiry time.
+
+### Image
+
+At this point, you probably ask yourself: "okay, but to install Jekyll
+I need Ruby. Where is Ruby on that script?". The answer is simple: the
+first thing GitLab Runner will look for in your `.gitlab-ci.yml` is a
+[Docker](https://www.docker.com/) image specifying what do you need in
+your container to run that script:
+
+```yaml
+image: ruby:2.3
+
+pages:
+ script:
+ - bundle install
+ - bundle exec jekyll build -d public
+ artifacts:
+ paths:
+ - public
+```
+
+In this case, you're telling the Runner to pull this image, which
+contains Ruby 2.3 as part of its file system. When you don't specify
+this image in your configuration, the Runner will use a default
+image, which is Ruby 2.1.
+
+If your SSG needs [NodeJS](https://nodejs.org/) to build, you'll
+need to specify which image you want to use, and this image should
+contain NodeJS as part of its file system. E.g., for a
+[Hexo](https://gitlab.com/pages/hexo) site, you can use `image: node:4.2.2`.
+
+>**Note:**
+We're not trying to explain what a Docker image is,
+we just need to introduce the concept with a minimum viable
+explanation. To know more about Docker images, please visit
+their website or take a look at a
+[summarized explanation](http://paislee.io/how-to-automate-docker-deployments/) here.
+
+Let's go a little further.
+
+### Branching
+
+If you use GitLab as a version control platform, you will have your
+branching strategy to work on your project. Meaning, you will have
+other branches in your project, but you'll want only pushes to the
+default branch (usually `master`) to be deployed to your website.
+To do that, we need to add another line to our CI, telling the Runner
+to only perform that _job_ called `pages` on the `master` branch `only`:
+
+```yaml
+image: ruby:2.3
+
+pages:
+ script:
+ - bundle install
+ - bundle exec jekyll build -d public
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
+```
+
+### Stages
+
+Another interesting concept to keep in mind are build stages.
+Your web app can pass through a lot of tests and other tasks
+until it's deployed to staging or production environments.
+There are three default stages on GitLab CI: build, test,
+and deploy. To specify which stage your _job_ is running,
+simply add another line to your CI:
+
+```yaml
+image: ruby:2.3
+
+pages:
+ stage: deploy
+ script:
+ - bundle install
+ - bundle exec jekyll build -d public
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
+```
+
+You might ask yourself: "why should I bother with stages
+at all?" Well, let's say you want to be able to test your
+script and check the built site before deploying your site
+to production. You want to run the test exactly as your
+script will do when you push to `master`. It's simple,
+let's add another task (_job_) to our CI, telling it to
+test every push to other branches, `except` the `master` branch:
+
+```yaml
+image: ruby:2.3
+
+pages:
+ stage: deploy
+ script:
+ - bundle install
+ - bundle exec jekyll build -d public
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
+
+test:
+ stage: test
+ script:
+ - bundle install
+ - bundle exec jekyll build -d test
+ artifacts:
+ paths:
+ - test
+ except:
+ - master
+```
+
+The `test` job is running on the stage `test`, Jekyll
+will build the site in a directory called `test`, and
+this job will affect all the branches except `master`.
+
+The best benefit of applying _stages_ to different
+_jobs_ is that every job in the same stage builds in
+parallel. So, if your web app needs more than one test
+before being deployed, you can run all your test at the
+same time, it's not necessary to wait one test to finish
+to run the other. Of course, this is just a brief
+introduction of GitLab CI and GitLab Runner, which are
+tools much more powerful than that. This is what you
+need to be able to create and tweak your builds for
+your GitLab Pages site.
+
+### Before Script
+
+To avoid running the same script multiple times across
+your _jobs_, you can add the parameter `before_script`,
+in which you specify which commands you want to run for
+every single _job_. In our example, notice that we run
+`bundle install` for both jobs, `pages` and `test`.
+We don't need to repeat it:
+
+```yaml
+image: ruby:2.3
+
+before_script:
+ - bundle install
+
+pages:
+ stage: deploy
+ script:
+ - bundle exec jekyll build -d public
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
+
+test:
+ stage: test
+ script:
+ - bundle exec jekyll build -d test
+ artifacts:
+ paths:
+ - test
+ except:
+ - master
+```
+
+### Caching Dependencies
+
+If you want to cache the installation files for your
+projects dependencies, for building faster, you can
+use the parameter `cache`. For this example, we'll
+cache Jekyll dependencies in a `vendor` directory
+when we run `bundle install`:
+
+```yaml
+image: ruby:2.3
+
+cache:
+ paths:
+ - vendor/
+
+before_script:
+ - bundle install --path vendor
+
+pages:
+ stage: deploy
+ script:
+ - bundle exec jekyll build -d public
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
+
+test:
+ stage: test
+ script:
+ - bundle exec jekyll build -d test
+ artifacts:
+ paths:
+ - test
+ except:
+ - master
+```
+
+For this specific case, we need to exclude `/vendor`
+from Jekyll `_config.yml` file, otherwise Jekyll will
+understand it as a regular directory to build
+together with the site:
+
+```yml
+exclude:
+ - vendor
+```
+
+There we go! Now our GitLab CI not only builds our website,
+but also **continuously test** pushes to feature-branches,
+**caches** dependencies installed with Bundler, and
+**continuously deploy** every push to the `master` branch.
+
+## Advanced GitLab CI for GitLab Pages
+
+What you can do with GitLab CI is pretty much up to your
+creativity. Once you get used to it, you start creating
+awesome scripts that automate most of tasks you'd do
+manually in the past. Read through the
+[documentation of GitLab CI](https://docs.gitlab.com/ce/ci/yaml/README.html)
+to understand how to go even further on your scripts.
+
+- On this blog post, understand the concept of
+[using GitLab CI `environments` to deploy your
+web app to staging and production](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/).
+- On this post, learn [how to run jobs sequentially,
+in parallel, or build a custom pipeline](https://about.gitlab.com/2016/07/29/the-basics-of-gitlab-ci/)
+- On this blog post, we go through the process of
+[pulling specific directories from different projects](https://about.gitlab.com/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/)
+to deploy this website you're looking at, docs.gitlab.com.
+- On this blog post, we teach you [how to use GitLab Pages to produce a code coverage report](https://about.gitlab.com/2016/11/03/publish-code-coverage-report-with-gitlab-pages/).
+
+|||
+|:--|--:|
+|[**← Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates**](getting_started_part_three.md)||
diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md
new file mode 100644
index 00000000000..2f104c7becc
--- /dev/null
+++ b/doc/user/project/pages/getting_started_part_one.md
@@ -0,0 +1,111 @@
+# GitLab Pages from A to Z: Part 1
+
+> **Article [Type](../../../development/writing_documentation.html#types-of-technical-articles)**: user guide ||
+> **Level**: beginner ||
+> **Author**: [Marcia Ramos](https://gitlab.com/marcia) ||
+> **Publication date:** 2017/02/22
+
+- **Part 1: Static sites and GitLab Pages domains**
+- [Part 2: Quick start guide - Setting up GitLab Pages](getting_started_part_two.md)
+- [Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](getting_started_part_three.md)
+- [Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_four.md)
+
+## GitLab Pages from A to Z
+
+This is a comprehensive guide, made for those who want to
+publish a website with GitLab Pages but aren't familiar with
+the entire process involved.
+
+This [first part](#what-you-need-to-know-before-getting-started) of this series will present you to the concepts of
+static sites, and go over how the default Pages domains work.
+
+The [second part](getting_started_part_two.md) covers how to get started with GitLab Pages: deploy
+a website from a forked project or create a new one from scratch.
+
+The [third part](getting_started_part_three.md) will show you how to set up a custom domain or subdomain
+to your site already deployed.
+
+The [fourth part](getting_started_part_four.md) will show you how to create and tweak GitLab CI for
+GitLab Pages.
+
+To **enable** GitLab Pages for GitLab CE (Community Edition)
+and GitLab EE (Enterprise Edition), please read the
+[admin documentation](https://docs.gitlab.com/ce/administration/pages/index.html),
+and/or watch this [video tutorial](https://youtu.be/dD8c7WNcc6s).
+
+>**Note:**
+For this guide, we assume you already have GitLab Pages
+server up and running for your GitLab instance.
+
+## What you need to know before getting started
+
+Before we begin, let's understand a few concepts first.
+
+### Static sites
+
+GitLab Pages only supports static websites, meaning,
+your output files must be HTML, CSS, and JavaScript only.
+
+To create your static site, you can either hardcode in HTML,
+CSS, and JS, or use a [Static Site Generator (SSG)](https://www.staticgen.com/)
+to simplify your code and build the static site for you,
+which is highly recommendable and much faster than hardcoding.
+
+#### Further Reading
+
+- Read through this technical overview on [Static versus Dynamic Websites](https://about.gitlab.com/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/)
+- Understand [how modern Static Site Generators work](https://about.gitlab.com/2016/06/10/ssg-overview-gitlab-pages-part-2/) and what you can add to your static site
+- You can use [any SSG with GitLab Pages](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/)
+- Fork an [example project](https://gitlab.com/pages) to build your website based upon
+
+### GitLab Pages domain
+
+If you set up a GitLab Pages project on GitLab.com,
+it will automatically be accessible under a
+[subdomain of `namespace.pages.io`](https://docs.gitlab.com/ce/user/project/pages/).
+The `namespace` is defined by your username on GitLab.com,
+or the group name you created this project under.
+
+>**Note:**
+If you use your own GitLab instance to deploy your
+site with GitLab Pages, check with your sysadmin what's your
+Pages wildcard domain. This guide is valid for any GitLab instance,
+you just need to replace Pages wildcard domain on GitLab.com
+(`*.gitlab.io`) with your own.
+
+#### Practical examples
+
+**Project Websites:**
+
+- You created a project called `blog` under your username `john`,
+therefore your project URL is `https://gitlab.com/john/blog/`.
+Once you enable GitLab Pages for this project, and build your site,
+it will be available under `https://john.gitlab.io/blog/`.
+- You created a group for all your websites called `websites`,
+and a project within this group is called `blog`. Your project
+URL is `https://gitlab.com/websites/blog/`. Once you enable
+GitLab Pages for this project, the site will live under
+`https://websites.gitlab.io/blog/`.
+
+**User and Group Websites:**
+
+- Under your username, `john`, you created a project called
+`john.gitlab.io`. Your project URL will be `https://gitlab.com/john/john.gitlab.io`.
+Once you enable GitLab Pages for your project, your website
+will be published under `https://john.gitlab.io`.
+- Under your group `websites`, you created a project called
+`websites.gitlab.io`. your project's URL will be `https://gitlab.com/websites/websites.gitlab.io`. Once you enable GitLab Pages for your project,
+your website will be published under `https://websites.gitlab.io`.
+
+**General example:**
+
+- On GitLab.com, a project site will always be available under
+`https://namespace.gitlab.io/project-name`
+- On GitLab.com, a user or group website will be available under
+`https://namespace.gitlab.io/`
+- On your GitLab instance, replace `gitlab.io` above with your
+Pages server domain. Ask your sysadmin for this information.
+
+|||
+|:--|--:|
+||[**Part 2: Quick start guide - Setting up GitLab Pages →**](getting_started_part_two.md)|
diff --git a/doc/user/project/pages/getting_started_part_three.md b/doc/user/project/pages/getting_started_part_three.md
new file mode 100644
index 00000000000..53fd1786cfa
--- /dev/null
+++ b/doc/user/project/pages/getting_started_part_three.md
@@ -0,0 +1,195 @@
+# GitLab Pages from A to Z: Part 3
+
+> **Article [Type](../../../development/writing_documentation.html#types-of-technical-articles)**: user guide ||
+> **Level**: beginner ||
+> **Author**: [Marcia Ramos](https://gitlab.com/marcia) ||
+> **Publication date:** 2017/02/22
+
+- [Part 1: Static sites and GitLab Pages domains](getting_started_part_one.md)
+- [Part 2: Quick start guide - Setting up GitLab Pages](getting_started_part_two.md)
+- **Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates**
+- [Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_four.md)
+
+## Setting Up Custom Domains - DNS Records and SSL/TLS Certificates
+
+As described in the previous part of this series, setting up GitLab Pages with custom domains, and adding SSL/TLS certificates to them, are optional features of GitLab Pages.
+
+These steps assume you've already [set your site up](getting_started_part_two.md) and and it's served under the default Pages domain `namespace.gitlab.io`, or `namespace.gitlab.io/project-name`.
+
+### DNS Records
+
+A Domain Name System (DNS) web service routes visitors to websites
+by translating domain names (such as `www.example.com`) into the
+numeric IP addresses (such as `192.0.2.1`) that computers use to
+connect to each other.
+
+A DNS record is created to point a (sub)domain to a certain location,
+which can be an IP address or another domain. In case you want to use
+GitLab Pages with your own (sub)domain, you need to access your domain's
+registrar control panel to add a DNS record pointing it back to your
+GitLab Pages site.
+
+Note that **how to** add DNS records depends on which server your domain
+is hosted on. Every control panel has its own place to do it. If you are
+not an admin of your domain, and don't have access to your registrar,
+you'll need to ask for the technical support of your hosting service
+to do it for you.
+
+To help you out, we've gathered some instructions on how to do that
+for the most popular hosting services:
+
+- [Amazon](http://docs.aws.amazon.com/gettingstarted/latest/swh/getting-started-configure-route53.html)
+- [Bluehost](https://my.bluehost.com/cgi/help/559)
+- [CloudFlare](https://support.cloudflare.com/hc/en-us/articles/200169096-How-do-I-add-A-records-)
+- [cPanel](https://documentation.cpanel.net/display/ALD/Edit+DNS+Zone)
+- [DreamHost](https://help.dreamhost.com/hc/en-us/articles/215414867-How-do-I-add-custom-DNS-records-)
+- [Go Daddy](https://www.godaddy.com/help/add-an-a-record-19238)
+- [Hostgator](http://support.hostgator.com/articles/changing-dns-records)
+- [Inmotion hosting](https://my.bluehost.com/cgi/help/559)
+- [Media Temple](https://mediatemple.net/community/products/dv/204403794/how-can-i-change-the-dns-records-for-my-domain)
+- [Microsoft](https://msdn.microsoft.com/en-us/library/bb727018.aspx)
+
+If your hosting service is not listed above, you can just try to
+search the web for "how to add dns record on <my hosting service>".
+
+#### DNS A record
+
+In case you want to point a root domain (`example.com`) to your
+GitLab Pages site, deployed to `namespace.gitlab.io`, you need to
+log into your domain's admin control panel and add a DNS `A` record
+pointing your domain to Pages' server IP address. For projects on
+GitLab.com, this IP is `52.167.214.135`. For projects leaving in
+other GitLab instances (CE or EE), please contact your sysadmin
+asking for this information (which IP address is Pages server
+running on your instance).
+
+**Practical Example:**
+
+![DNS A record pointing to GitLab.com Pages server](img/dns_add_new_a_record_example_updated.png)
+
+#### DNS CNAME record
+
+In case you want to point a subdomain (`hello-world.example.com`)
+to your GitLab Pages site initially deployed to `namespace.gitlab.io`,
+you need to log into your domain's admin control panel and add a DNS
+`CNAME` record pointing your subdomain to your website URL
+(`namespace.gitlab.io`) address.
+
+Notice that, despite it's a user or project website, the `CNAME`
+should point to your Pages domain (`namespace.gitlab.io`),
+without any `/project-name`.
+
+**Practical Example:**
+
+![DNS CNAME record pointing to GitLab.com project](img/dns_cname_record_example.png)
+
+#### TL;DR
+
+| From | DNS Record | To |
+| ---- | ---------- | -- |
+| domain.com | A | 52.167.214.135 |
+| subdomain.domain.com | CNAME | namespace.gitlab.io |
+
+> **Notes**:
+>
+> - **Do not** use a CNAME record if you want to point your
+`domain.com` to your GitLab Pages site. Use an `A` record instead.
+> - **Do not** add any special chars after the default Pages
+domain. E.g., **do not** point your `subdomain.domain.com` to
+`namespace.gitlab.io.` or `namespace.gitlab.io/`.
+> - GitLab Pages IP on GitLab.com [has been changed](https://about.gitlab.com/2017/03/06/we-are-changing-the-ip-of-gitlab-pages-on-gitlab-com/) from `104.208.235.32` to `52.167.214.135`.
+
+### SSL/TLS Certificates
+
+Every GitLab Pages project on GitLab.com will be available under
+HTTPS for the default Pages domain (`*.gitlab.io`). Once you set
+up your Pages project with your custom (sub)domain, if you want
+it secured by HTTPS, you will have to issue a certificate for that
+(sub)domain and install it on your project.
+
+>**Note:**
+Certificates are NOT required to add to your custom
+(sub)domain on your GitLab Pages project, though they are
+highly recommendable.
+
+The importance of having any website securely served under HTTPS
+is explained on the introductory section of the blog post
+[Secure GitLab Pages with StartSSL](https://about.gitlab.com/2016/06/24/secure-gitlab-pages-with-startssl/#https-a-quick-overview).
+
+The reason why certificates are so important is that they encrypt
+the connection between the **client** (you, me, your visitors)
+and the **server** (where you site lives), through a keychain of
+authentications and validations.
+
+### Issuing Certificates
+
+GitLab Pages accepts [PEM](https://support.quovadisglobal.com/kb/a37/what-is-pem-format.aspx) certificates issued by
+[Certificate Authorities (CA)](https://en.wikipedia.org/wiki/Certificate_authority)
+and self-signed certificates. Of course,
+[you'd rather issue a certificate than generate a self-signed](https://en.wikipedia.org/wiki/Self-signed_certificate),
+for security reasons and for having browsers trusting your
+site's certificate.
+
+There are several different kinds of certificates, each one
+with certain security level. A static personal website will
+not require the same security level as an online banking web app,
+for instance. There are a couple Certificate Authorities that
+offer free certificates, aiming to make the internet more secure
+to everyone. The most popular is [Let's Encrypt](https://letsencrypt.org/),
+which issues certificates trusted by most of browsers, it's open
+source, and free to use. Please read through this tutorial to
+understand [how to secure your GitLab Pages website with Let's Encrypt](https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/).
+
+With the same popularity, there are [certificates issued by CloudFlare](https://www.cloudflare.com/ssl/),
+which also offers a [free CDN service](https://blog.cloudflare.com/cloudflares-free-cdn-and-you/).
+Their certs are valid up to 15 years. Read through the tutorial on
+[how to add a CloudFlare Certificate to your GitLab Pages website](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/).
+
+### Adding certificates to your project
+
+Regardless the CA you choose, the steps to add your certificate to
+your Pages project are the same.
+
+#### What do you need
+
+1. A PEM certificate
+1. An intermediate certificate
+1. A public key
+
+![Pages project - adding certificates](img/add_certificate_to_pages.png)
+
+These fields are found under your **Project**'s **Settings** > **Pages** > **New Domain**.
+
+#### What's what?
+
+- A PEM certificate is the certificate generated by the CA,
+which needs to be added to the field **Certificate (PEM)**.
+- An [intermediate certificate](https://en.wikipedia.org/wiki/Intermediate_certificate_authority) (aka "root certificate") is
+the part of the encryption keychain that identifies the CA.
+Usually it's combined with the PEM certificate, but there are
+some cases in which you need to add them manually.
+[CloudFlare certs](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/)
+are one of these cases.
+- A public key is an encrypted key which validates
+your PEM against your domain.
+
+#### Now what?
+
+Now that you hopefully understand why you need all
+of this, it's simple:
+
+- Your PEM certificate needs to be added to the first field
+- If your certificate is missing its intermediate, copy
+and paste the root certificate (usually available from your CA website)
+and paste it in the [same field as your PEM certificate](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/),
+just jumping a line between them.
+- Copy your public key and paste it in the last field
+
+>**Note:**
+**Do not** open certificates or encryption keys in
+regular text editors. Always use code editors (such as
+Sublime Text, Atom, Dreamweaver, Brackets, etc).
+
+|||
+|:--|--:|
+|[**← Part 2: Quick start guide - Setting up GitLab Pages**](getting_started_part_two.md)|[**Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages →**](getting_started_part_four.md)|
diff --git a/doc/user/project/pages/getting_started_part_two.md b/doc/user/project/pages/getting_started_part_two.md
new file mode 100644
index 00000000000..64de0463dad
--- /dev/null
+++ b/doc/user/project/pages/getting_started_part_two.md
@@ -0,0 +1,159 @@
+# GitLab Pages from A to Z: Part 2
+
+> **Article [Type](../../../development/writing_documentation.html#types-of-technical-articles)**: user guide ||
+> **Level**: beginner ||
+> **Author**: [Marcia Ramos](https://gitlab.com/marcia) ||
+> **Publication date:** 2017/02/22
+
+- [Part 1: Static sites and GitLab Pages domains](getting_started_part_one.md)
+- **Part 2: Quick start guide - Setting up GitLab Pages**
+- [Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](getting_started_part_three.md)
+- [Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_four.md)
+
+## Setting up GitLab Pages
+
+For a complete step-by-step tutorial, please read the
+blog post [Hosting on GitLab.com with GitLab Pages](https://about.gitlab.com/2016/04/07/gitlab-pages-setup/). The following sections will explain
+what do you need and why do you need them.
+
+## What you need to get started
+
+1. A project
+1. A configuration file (`.gitlab-ci.yml`) to deploy your site
+1. A specific `job` called `pages` in the configuration file
+that will make GitLab aware that you are deploying a GitLab Pages website
+
+Optional Features:
+
+1. A custom domain or subdomain
+1. A DNS pointing your (sub)domain to your Pages site
+ 1. **Optional**: an SSL/TLS certificate so your custom
+ domain is accessible under HTTPS.
+
+The optional settings, custom domain, DNS records, and SSL/TLS certificates, are described in [Part 3](getting_started_part_three.md)).
+
+## Project
+
+Your GitLab Pages project is a regular project created the
+same way you do for the other ones. To get started with GitLab Pages, you have two ways:
+
+- Fork one of the templates from Page Examples, or
+- Create a new project from scratch
+
+Let's go over both options.
+
+### Fork a project to get started from
+
+To make things easy for you, we've created this
+[group](https://gitlab.com/pages) of default projects
+containing the most popular SSGs templates.
+
+Watch the [video tutorial](https://youtu.be/TWqh9MtT4Bg) we've
+created for the steps below.
+
+1. Choose your SSG template
+1. Fork a project from the [Pages group](https://gitlab.com/pages)
+1. Remove the fork relationship by navigating to your **Project**'s **Settings** > **Edit Project**
+
+ ![remove fork relashionship](img/remove_fork_relashionship.png)
+
+1. Enable Shared Runners for your fork: navigate to your **Project**'s **Settings** > **Pipelines**
+1. Trigger a build (push a change to any file)
+1. As soon as the build passes, your website will have been deployed with GitLab Pages. Your website URL will be available under your **Project**'s **Settings** > **Pages**
+
+To turn a **project website** forked from the Pages group into a **user/group** website, you'll need to:
+
+- Rename it to `namespace.gitlab.io`: navigate to **Project**'s **Settings** > **Edit Project** > **Rename repository**
+- Adjust your SSG's [base URL](#urls-and-baseurls) to from `"project-name"` to `""`. This setting will be at a different place for each SSG, as each of them have their own structure and file tree. Most likelly, it will be in the SSG's config file.
+
+> **Notes:**
+>
+>1. Why do I need to remove the fork relationship?
+>
+> Unless you want to contribute to the original project,
+you won't need it connected to the upstream. A
+[fork](https://about.gitlab.com/2016/12/01/how-to-keep-your-fork-up-to-date-with-its-origin/#fork)
+is useful for submitting merge requests to the upstream.
+>
+> 2. Why do I need to enable Shared Runners?
+>
+> Shared Runners will run the script set by your GitLab CI
+configuration file. They're enabled by default to new projects,
+but not to forks.
+
+### Create a project from scratch
+
+1. From your **Project**'s **[Dashboard](https://gitlab.com/dashboard/projects)**,
+click **New project**, and name it considering the
+[practical examples](getting_started_part_one.md#practical-examples).
+1. Clone it to your local computer, add your website
+files to your project, add, commit and push to GitLab.
+1. From the your **Project**'s page, click **Set up CI**:
+
+ ![setup GitLab CI](img/setup_ci.png)
+
+1. Choose one of the templates from the dropbox menu.
+Pick up the template corresponding to the SSG you're using (or plain HTML).
+
+ ![gitlab-ci templates](img/choose_ci_template.png)
+
+Once you have both site files and `.gitlab-ci.yml` in your project's
+root, GitLab CI will build your site and deploy it with Pages.
+Once the first build passes, you see your site is live by
+navigating to your **Project**'s **Settings** > **Pages**,
+where you'll find its default URL.
+
+> **Notes:**
+>
+> - GitLab Pages [supports any SSG](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/), but,
+if you don't find yours among the templates, you'll need
+to configure your own `.gitlab-ci.yml`. Do do that, please
+read through the article [Creating and Tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_four.md). New SSGs are very welcome among
+the [example projects](https://gitlab.com/pages). If you set
+up a new one, please
+[contribute](https://gitlab.com/pages/pages.gitlab.io/blob/master/CONTRIBUTING.md)
+to our examples.
+>
+> - The second step _"Clone it to your local computer"_, can be done
+differently, achieving the same results: instead of cloning the bare
+repository to you local computer and moving your site files into it,
+you can run `git init` in your local website directory, add the
+remote URL: `git remote add origin git@gitlab.com:namespace/project-name.git`,
+then add, commit, and push.
+
+### URLs and Baseurls
+
+Every Static Site Generator (SSG) default configuration expects
+to find your website under a (sub)domain (`example.com`), not
+in a subdirectory of that domain (`example.com/subdir`). Therefore,
+whenever you publish a project website (`namespace.gitlab.io/project-name`),
+you'll have to look for this configuration (base URL) on your SSG's
+documentation and set it up to reflect this pattern.
+
+For example, for a Jekyll site, the `baseurl` is defined in the Jekyll
+configuration file, `_config.yml`. If your website URL is
+`https://john.gitlab.io/blog/`, you need to add this line to `_config.yml`:
+
+```yaml
+baseurl: "/blog"
+```
+
+On the contrary, if you deploy your website after forking one of
+our [default examples](https://gitlab.com/pages), the baseurl will
+already be configured this way, as all examples there are project
+websites. If you decide to make yours a user or group website, you'll
+have to remove this configuration from your project. For the Jekyll
+example we've just mentioned, you'd have to change Jekyll's `_config.yml` to:
+
+```yaml
+baseurl: ""
+```
+
+### Custom Domains
+
+GitLab Pages supports custom domains and subdomains, served under HTTPS or HTTPS.
+Please check the [next part](getting_started_part_three.md) of this series for an overview.
+
+|||
+|:--|--:|
+|[**← Part 1: Static sites, domains, DNS records, and SSL/TLS certificates**](getting_started_part_one.md)|[**Setting Up Custom Domains - DNS Records and SSL/TLS Certificates →**](getting_started_part_three.md)|
diff --git a/doc/user/project/pages/img/add_certificate_to_pages.png b/doc/user/project/pages/img/add_certificate_to_pages.png
new file mode 100644
index 00000000000..d92a981dc60
--- /dev/null
+++ b/doc/user/project/pages/img/add_certificate_to_pages.png
Binary files differ
diff --git a/doc/user/project/pages/img/choose_ci_template.png b/doc/user/project/pages/img/choose_ci_template.png
new file mode 100644
index 00000000000..0697542abc8
--- /dev/null
+++ b/doc/user/project/pages/img/choose_ci_template.png
Binary files differ
diff --git a/doc/user/project/pages/img/dns_add_new_a_record_example_updated.png b/doc/user/project/pages/img/dns_add_new_a_record_example_updated.png
new file mode 100644
index 00000000000..2661a497b91
--- /dev/null
+++ b/doc/user/project/pages/img/dns_add_new_a_record_example_updated.png
Binary files differ
diff --git a/doc/user/project/pages/img/dns_cname_record_example.png b/doc/user/project/pages/img/dns_cname_record_example.png
new file mode 100644
index 00000000000..43d1a838544
--- /dev/null
+++ b/doc/user/project/pages/img/dns_cname_record_example.png
Binary files differ
diff --git a/doc/user/project/pages/img/pages_create_project.png b/doc/user/project/pages/img/pages_create_project.png
new file mode 100644
index 00000000000..be47f9d2a44
--- /dev/null
+++ b/doc/user/project/pages/img/pages_create_project.png
Binary files differ
diff --git a/doc/user/project/pages/img/pages_create_user_page.png b/doc/user/project/pages/img/pages_create_user_page.png
new file mode 100644
index 00000000000..2f1a19ae424
--- /dev/null
+++ b/doc/user/project/pages/img/pages_create_user_page.png
Binary files differ
diff --git a/doc/user/project/pages/img/pages_dns_details.png b/doc/user/project/pages/img/pages_dns_details.png
new file mode 100644
index 00000000000..274e98fde4d
--- /dev/null
+++ b/doc/user/project/pages/img/pages_dns_details.png
Binary files differ
diff --git a/doc/user/project/pages/img/pages_multiple_domains.png b/doc/user/project/pages/img/pages_multiple_domains.png
new file mode 100644
index 00000000000..6bc92db6b41
--- /dev/null
+++ b/doc/user/project/pages/img/pages_multiple_domains.png
Binary files differ
diff --git a/doc/user/project/pages/img/pages_new_domain_button.png b/doc/user/project/pages/img/pages_new_domain_button.png
new file mode 100644
index 00000000000..cd59defa006
--- /dev/null
+++ b/doc/user/project/pages/img/pages_new_domain_button.png
Binary files differ
diff --git a/doc/user/project/pages/img/pages_remove.png b/doc/user/project/pages/img/pages_remove.png
new file mode 100644
index 00000000000..b064310380e
--- /dev/null
+++ b/doc/user/project/pages/img/pages_remove.png
Binary files differ
diff --git a/doc/user/project/pages/img/pages_upload_cert.png b/doc/user/project/pages/img/pages_upload_cert.png
new file mode 100644
index 00000000000..dc431ea3fef
--- /dev/null
+++ b/doc/user/project/pages/img/pages_upload_cert.png
Binary files differ
diff --git a/doc/user/project/pages/img/remove_fork_relashionship.png b/doc/user/project/pages/img/remove_fork_relashionship.png
new file mode 100644
index 00000000000..67c45491f08
--- /dev/null
+++ b/doc/user/project/pages/img/remove_fork_relashionship.png
Binary files differ
diff --git a/doc/user/project/pages/img/setup_ci.png b/doc/user/project/pages/img/setup_ci.png
new file mode 100644
index 00000000000..214c1cc668f
--- /dev/null
+++ b/doc/user/project/pages/img/setup_ci.png
Binary files differ
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
new file mode 100644
index 00000000000..abe6b4cbd8e
--- /dev/null
+++ b/doc/user/project/pages/index.md
@@ -0,0 +1,49 @@
+# GitLab Pages documentation
+
+With GitLab Pages you can create static websites for your GitLab projects,
+groups, or user accounts. You can use any static website generator: Jekyll,
+Middleman, Hexo, Hugo, Pelican, you name it! Connect as many customs domains
+as you like and bring your own TLS certificate to secure them.
+
+Here's some info we've gathered to get you started.
+
+## General info
+
+- [Product webpage](https://pages.gitlab.io)
+- ["We're bringing GitLab Pages to CE"](https://about.gitlab.com/2016/12/24/were-bringing-gitlab-pages-to-community-edition/)
+- [Pages group - templates](https://gitlab.com/pages)
+- [General user documentation](introduction.md)
+- [Admin documentation - Set GitLab Pages on your own GitLab instance](../../../administration/pages/index.md)
+- ["We are changing the IP of GitLab Pages on GitLab.com"](https://about.gitlab.com/2017/03/06/we-are-changing-the-ip-of-gitlab-pages-on-gitlab-com/)
+
+## Getting started
+
+- **GitLab Pages from A to Z**
+ - [Part 1: Static sites and GitLab Pages domains](getting_started_part_one.md)
+ - [Part 2: Quick start guide - Setting up GitLab Pages](getting_started_part_two.md)
+ - [Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](getting_started_part_three.md)
+ - [Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_four.md)
+- **Static Site Generators - Blog posts series**
+ - [SSGs part 1: Static vs dynamic websites](https://about.gitlab.com/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/)
+ - [SSGs part 2: Modern static site generators](https://about.gitlab.com/2016/06/10/ssg-overview-gitlab-pages-part-2/)
+ - [SSGs part 3: Build any SSG site with GitLab Pages](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/)
+- **Secure GitLab Pages custom domain with SSL/TLS certificates**
+ - [Let's Encrypt](https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/)
+ - [CloudFlare](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/)
+ - [StartSSL](https://about.gitlab.com/2016/06/24/secure-gitlab-pages-with-startssl/)
+- **General**
+ - [Hosting on GitLab.com with GitLab Pages](https://about.gitlab.com/2016/04/07/gitlab-pages-setup/) a comprehensive step-by-step guide
+ - [Posting to your GitLab Pages blog from iOS](https://about.gitlab.com/2016/08/19/posting-to-your-gitlab-pages-blog-from-ios/)
+
+## Video tutorials
+
+- [How to publish a website with GitLab Pages on GitLab.com: from a forked project](https://youtu.be/TWqh9MtT4Bg)
+- [How to Enable GitLab Pages for GitLab CE and EE (for Admins only)](https://youtu.be/dD8c7WNcc6s)
+
+## Advanced use
+
+- **Blog Posts**
+ - [GitLab CI: Run jobs sequentially, in parallel, or build a custom pipeline](https://about.gitlab.com/2016/07/29/the-basics-of-gitlab-ci/)
+ - [GitLab CI: Deployment & environments](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/)
+ - [Building a new GitLab docs site with Nanoc, GitLab CI, and GitLab Pages](https://about.gitlab.com/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/)
+ - [Publish code coverage reports with GitLab Pages](https://about.gitlab.com/2016/11/03/publish-code-coverage-report-with-gitlab-pages/)
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
new file mode 100644
index 00000000000..deaceabb7c5
--- /dev/null
+++ b/doc/user/project/pages/introduction.md
@@ -0,0 +1,447 @@
+# GitLab Pages
+
+> **Notes:**
+> - This feature was [introduced][ee-80] in GitLab EE 8.3.
+> - Custom CNAMEs with TLS support were [introduced][ee-173] in GitLab EE 8.5.
+> - GitLab Pages [were ported][ce-14605] to Community Edition in GitLab 8.17.
+> - This document is about the user guide. To learn how to enable GitLab Pages
+> across your GitLab instance, visit the [administrator documentation](../../../administration/pages/index.md).
+
+With GitLab Pages you can host for free your static websites on GitLab.
+Combined with the power of [GitLab CI] and the help of [GitLab Runner] you can
+deploy static pages for your individual projects, your user or your group.
+
+Read [GitLab Pages on GitLab.com](#gitlab-pages-on-gitlab-com) for specific
+information, if you are using GitLab.com to host your website.
+
+Read through [All you Need to Know About GitLab Pages][pages-index-guide] for a list of all learning materials we have prepared for GitLab Pages (webpages, articles, guides, blog posts, video tutorials).
+
+## Getting started with GitLab Pages
+
+> **Note:**
+> In the rest of this document we will assume that the general domain name that
+> is used for GitLab Pages is `example.io`.
+
+In general there are two types of pages one might create:
+
+- Pages per user (`username.example.io`) or per group (`groupname.example.io`)
+- Pages per project (`username.example.io/projectname` or `groupname.example.io/projectname`)
+
+In GitLab, usernames and groupnames are unique and we often refer to them
+as namespaces. There can be only one namespace in a GitLab instance. Below you
+can see the connection between the type of GitLab Pages, what the project name
+that is created on GitLab looks like and the website URL it will be ultimately
+be served on.
+
+| Type of GitLab Pages | The name of the project created in GitLab | Website URL |
+| -------------------- | ------------ | ----------- |
+| User pages | `username.example.io` | `http(s)://username.example.io` |
+| Group pages | `groupname.example.io` | `http(s)://groupname.example.io` |
+| Project pages owned by a user | `projectname` | `http(s)://username.example.io/projectname` |
+| Project pages owned by a group | `projectname` | `http(s)://groupname.example.io/projectname`|
+
+> **Warning:**
+> There are some known [limitations](#limitations) regarding namespaces served
+> under the general domain name and HTTPS. Make sure to read that section.
+
+### GitLab Pages requirements
+
+In brief, this is what you need to upload your website in GitLab Pages:
+
+1. Find out the general domain name that is used for GitLab Pages
+ (ask your administrator). This is very important, so you should first make
+ sure you get that right.
+1. Create a project
+1. Push a [`.gitlab-ci.yml` file][yaml] in the root directory
+ of your repository with a specific job named [`pages`][pages]
+1. Set up a GitLab Runner to build your website
+
+> **Note:**
+If [shared runners](../../../ci/runners/README.md) are enabled by your GitLab
+administrator, you should be able to use them instead of bringing your own.
+
+### User or group Pages
+
+For user and group pages, the name of the project should be specific to the
+username or groupname and the general domain name that is used for GitLab Pages.
+Head over your GitLab instance that supports GitLab Pages and create a
+repository named `username.example.io`, where `username` is your username on
+GitLab. If the first part of the project name doesn't match exactly your
+username, it won’t work, so make sure to get it right.
+
+To create a group page, the steps are the same like when creating a website for
+users. Just make sure that you are creating the project within the group's
+namespace.
+
+![Create a user-based pages project](img/pages_create_user_page.png)
+
+---
+
+After you push some static content to your repository and GitLab Runner uploads
+the artifacts to GitLab CI, you will be able to access your website under
+`http(s)://username.example.io`. Keep reading to find out how.
+
+>**Note:**
+If your username/groupname contains a dot, for example `foo.bar`, you will not
+be able to use the wildcard domain HTTPS, read more at [limitations](#limitations).
+
+### Project Pages
+
+GitLab Pages for projects can be created by both user and group accounts.
+The steps to create a project page for a user or a group are identical:
+
+1. Create a new project
+1. Push a [`.gitlab-ci.yml` file][yaml] in the root directory
+ of your repository with a specific job named [`pages`][pages].
+1. Set up a GitLab Runner to build your website
+
+A user's project will be served under `http(s)://username.example.io/projectname`
+whereas a group's project under `http(s)://groupname.example.io/projectname`.
+
+## Quick Start
+
+Read through [GitLab Pages Quick Start Guide][pages-quick] or watch the video tutorial on
+[how to publish a website with GitLab Pages on GitLab.com from a forked project][video-pages-fork].
+
+See also [All you Need to Know About GitLab Pages][pages-index-guide] for a list with all the resources we have for GitLab Pages.
+
+### Explore the contents of `.gitlab-ci.yml`
+
+The key thing about GitLab Pages is the `.gitlab-ci.yml` file, something that
+gives you absolute control over the build process. You can actually watch your
+website being built live by following the CI job traces.
+
+> **Note:**
+> Before reading this section, make sure you familiarize yourself with GitLab CI
+> and the specific syntax of[`.gitlab-ci.yml`][yaml] by
+> following our [quick start guide].
+
+To make use of GitLab Pages, the contents of `.gitlab-ci.yml` must follow the
+rules below:
+
+1. A special job named [`pages`][pages] must be defined
+1. Any static content which will be served by GitLab Pages must be placed under
+ a `public/` directory
+1. `artifacts` with a path to the `public/` directory must be defined
+
+In its simplest form, `.gitlab-ci.yml` looks like:
+
+```yaml
+pages:
+ script:
+ - my_commands
+ artifacts:
+ paths:
+ - public
+```
+
+When the Runner reaches to build the `pages` job, it executes whatever is
+defined in the `script` parameter and if the job completes with a non-zero
+exit status, it then uploads the `public/` directory to GitLab Pages.
+
+The `public/` directory should contain all the static content of your website.
+Depending on how you plan to publish your website, the steps defined in the
+[`script` parameter](../../../ci/yaml/README.md#script) may differ.
+
+Be aware that Pages are by default branch/tag agnostic and their deployment
+relies solely on what you specify in `.gitlab-ci.yml`. If you don't limit the
+`pages` job with the [`only` parameter](../../../ci/yaml/README.md#only-and-except),
+whenever a new commit is pushed to whatever branch or tag, the Pages will be
+overwritten. In the example below, we limit the Pages to be deployed whenever
+a commit is pushed only on the `master` branch:
+
+```yaml
+pages:
+ script:
+ - my_commands
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
+```
+
+We then tell the Runner to treat the `public/` directory as `artifacts` and
+upload it to GitLab. And since all these parameters were all under a `pages`
+job, the contents of the `public` directory will be served by GitLab Pages.
+
+#### How `.gitlab-ci.yml` looks like when the static content is in your repository
+
+Supposedly your repository contained the following files:
+
+```
+├── index.html
+├── css
+│   └── main.css
+└── js
+ └── main.js
+```
+
+Then the `.gitlab-ci.yml` example below simply moves all files from the root
+directory of the project to the `public/` directory. The `.public` workaround
+is so `cp` doesn't also copy `public/` to itself in an infinite loop:
+
+```yaml
+pages:
+ script:
+ - mkdir .public
+ - cp -r * .public
+ - mv .public public
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
+```
+
+#### How `.gitlab-ci.yml` looks like when using a static generator
+
+In general, GitLab Pages support any kind of [static site generator][staticgen],
+since `.gitlab-ci.yml` can be configured to run any possible command.
+
+In the root directory of your Git repository, place the source files of your
+favorite static generator. Then provide a `.gitlab-ci.yml` file which is
+specific to your static generator.
+
+The example below, uses [Jekyll] to build the static site:
+
+```yaml
+image: ruby:2.1 # the script will run in Ruby 2.1 using the Docker image ruby:2.1
+
+pages: # the build job must be named pages
+ script:
+ - gem install jekyll # we install jekyll
+ - jekyll build -d public/ # we tell jekyll to build the site for us
+ artifacts:
+ paths:
+ - public # this is where the site will live and the Runner uploads it in GitLab
+ only:
+ - master # this script is only affecting the master branch
+```
+
+Here, we used the Docker executor and in the first line we specified the base
+image against which our jobs will run.
+
+You have to make sure that the generated static files are ultimately placed
+under the `public` directory, that's why in the `script` section we run the
+`jekyll` command that jobs the website and puts all content in the `public/`
+directory. Depending on the static generator of your choice, this command will
+differ. Search in the documentation of the static generator you will use if
+there is an option to explicitly set the output directory. If there is not
+such an option, you can always add one more line under `script` to rename the
+resulting directory in `public/`.
+
+We then tell the Runner to treat the `public/` directory as `artifacts` and
+upload it to GitLab.
+
+---
+
+See the [jekyll example project][pages-jekyll] to better understand how this
+works.
+
+For a list of Pages projects, see the [example projects](#example-projects) to
+get you started.
+
+#### How to set up GitLab Pages in a repository where there's also actual code
+
+Remember that GitLab Pages are by default branch/tag agnostic and their
+deployment relies solely on what you specify in `.gitlab-ci.yml`. You can limit
+the `pages` job with the [`only` parameter](../../../ci/yaml/README.md#only-and-except),
+whenever a new commit is pushed to a branch that will be used specifically for
+your pages.
+
+That way, you can have your project's code in the `master` branch and use an
+orphan branch (let's name it `pages`) that will host your static generator site.
+
+You can create a new empty branch like this:
+
+```bash
+git checkout --orphan pages
+```
+
+The first commit made on this new branch will have no parents and it will be
+the root of a new history totally disconnected from all the other branches and
+commits. Push the source files of your static generator in the `pages` branch.
+
+Below is a copy of `.gitlab-ci.yml` where the most significant line is the last
+one, specifying to execute everything in the `pages` branch:
+
+```
+image: ruby:2.1
+
+pages:
+ script:
+ - gem install jekyll
+ - jekyll build -d public/
+ artifacts:
+ paths:
+ - public
+ only:
+ - pages
+```
+
+See an example that has different files in the [`master` branch][jekyll-master]
+and the source files for Jekyll are in a [`pages` branch][jekyll-pages] which
+also includes `.gitlab-ci.yml`.
+
+[jekyll-master]: https://gitlab.com/pages/jekyll-branched/tree/master
+[jekyll-pages]: https://gitlab.com/pages/jekyll-branched/tree/pages
+
+## Next steps
+
+So you have successfully deployed your website, congratulations! Let's check
+what more you can do with GitLab Pages.
+
+### Example projects
+
+Below is a list of example projects for GitLab Pages with a plain HTML website
+or various static site generators. Contributions are very welcome.
+
+- [Plain HTML](https://gitlab.com/pages/plain-html)
+- [Jekyll](https://gitlab.com/pages/jekyll)
+- [Hugo](https://gitlab.com/pages/hugo)
+- [Middleman](https://gitlab.com/pages/middleman)
+- [Hexo](https://gitlab.com/pages/hexo)
+- [Brunch](https://gitlab.com/pages/brunch)
+- [Metalsmith](https://gitlab.com/pages/metalsmith)
+- [Harp](https://gitlab.com/pages/harp)
+
+Visit the GitLab Pages group for a full list of example projects:
+<https://gitlab.com/groups/pages>.
+
+### Add a custom domain to your Pages website
+
+If this setting is enabled by your GitLab administrator, you should be able to
+see the **New Domain** button when visiting your project's settings through the
+gear icon in the top right and then navigating to **Pages**.
+
+![New domain button](img/pages_new_domain_button.png)
+
+---
+
+You can add multiple domains pointing to your website hosted under GitLab.
+Once the domain is added, you can see it listed under the **Domains** section.
+
+![Pages multiple domains](img/pages_multiple_domains.png)
+
+---
+
+As a last step, you need to configure your DNS and add a CNAME pointing to your
+user/group page. Click on the **Details** button of a domain for further
+instructions.
+
+![Pages DNS details](img/pages_dns_details.png)
+
+---
+
+>**Note:**
+Currently there is support only for custom domains on per-project basis. That
+means that if you add a custom domain (`example.com`) for your user website
+(`username.example.io`), a project that is served under `username.example.io/foo`,
+will not be accessible under `example.com/foo`.
+
+### Secure your custom domain website with TLS
+
+When you add a new custom domain, you also have the chance to add a TLS
+certificate. If this setting is enabled by your GitLab administrator, you
+should be able to see the option to upload the public certificate and the
+private key when adding a new domain.
+
+![Pages upload cert](img/pages_upload_cert.png)
+
+### Custom error codes pages
+
+You can provide your own 403 and 404 error pages by creating the `403.html` and
+`404.html` files respectively in the root directory of the `public/` directory
+that will be included in the artifacts. Usually this is the root directory of
+your project, but that may differ depending on your static generator
+configuration.
+
+If the case of `404.html`, there are different scenarios. For example:
+
+- If you use project Pages (served under `/projectname/`) and try to access
+ `/projectname/non/exsiting_file`, GitLab Pages will try to serve first
+ `/projectname/404.html`, and then `/404.html`.
+- If you use user/group Pages (served under `/`) and try to access
+ `/non/existing_file` GitLab Pages will try to serve `/404.html`.
+- If you use a custom domain and try to access `/non/existing_file`, GitLab
+ Pages will try to serve only `/404.html`.
+
+### Remove the contents of your pages
+
+If you ever feel the need to purge your Pages content, you can do so by going
+to your project's settings through the gear icon in the top right, and then
+navigating to **Pages**. Hit the **Remove pages** button and your Pages website
+will be deleted. Simple as that.
+
+![Remove pages](img/pages_remove.png)
+
+## GitLab Pages on GitLab.com
+
+If you are using GitLab.com to host your website, then:
+
+- The general domain name for GitLab Pages on GitLab.com is `gitlab.io`.
+- Custom domains and TLS support are enabled.
+- Shared runners are enabled by default, provided for free and can be used to
+ build your website. If you want you can still bring your own Runner.
+
+The rest of the guide still applies.
+
+## Limitations
+
+When using Pages under the general domain of a GitLab instance (`*.example.io`),
+you _cannot_ use HTTPS with sub-subdomains. That means that if your
+username/groupname contains a dot, for example `foo.bar`, the domain
+`https://foo.bar.example.io` will _not_ work. This is a limitation of the
+[HTTP Over TLS protocol][rfc]. HTTP pages will continue to work provided you
+don't redirect HTTP to HTTPS.
+
+[rfc]: https://tools.ietf.org/html/rfc2818#section-3.1 "HTTP Over TLS RFC"
+
+## Redirects in GitLab Pages
+
+Since you cannot use any custom server configuration files, like `.htaccess` or
+any `.conf` file for that matter, if you want to redirect a web page to another
+location, you can use the [HTTP meta refresh tag][metarefresh].
+
+Some static site generators provide plugins for that functionality so that you
+don't have to create and edit HTML files manually. For example, Jekyll has the
+[redirect-from plugin](https://github.com/jekyll/jekyll-redirect-from).
+
+## Frequently Asked Questions
+
+### Can I download my generated pages?
+
+Sure. All you need to do is download the artifacts archive from the job page.
+
+### Can I use GitLab Pages if my project is private?
+
+Yes. GitLab Pages don't care whether you set your project's visibility level
+to private, internal or public.
+
+### Do I need to create a user/group website before creating a project website?
+
+No, you don't. You can create your project first and it will be accessed under
+`http(s)://namespace.example.io/projectname`.
+
+## Known issues
+
+For a list of known issues, visit GitLab's [public issue tracker].
+
+[jekyll]: http://jekyllrb.com/
+[ee-80]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/80
+[ee-173]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/173
+[pages-daemon]: https://gitlab.com/gitlab-org/gitlab-pages
+[gitlab ci]: https://about.gitlab.com/gitlab-ci
+[gitlab runner]: https://docs.gitlab.com/runner/
+[pages]: ../../../ci/yaml/README.md#pages
+[yaml]: ../../../ci/yaml/README.md
+[staticgen]: https://www.staticgen.com/
+[pages-jekyll]: https://gitlab.com/pages/jekyll
+[metarefresh]: https://en.wikipedia.org/wiki/Meta_refresh
+[public issue tracker]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=pages
+[ce-14605]: https://gitlab.com/gitlab-org/gitlab-ce/issues/14605
+[quick start guide]: ../../../ci/quick_start/README.md
+[pages-index-guide]: index.md
+[pages-quick]: getting_started_part_one.md
+[video-pages-fork]: https://youtu.be/TWqh9MtT4Bg
diff --git a/doc/user/project/pipelines/img/job_artifacts_browser.png b/doc/user/project/pipelines/img/job_artifacts_browser.png
new file mode 100644
index 00000000000..145fe156bbb
--- /dev/null
+++ b/doc/user/project/pipelines/img/job_artifacts_browser.png
Binary files differ
diff --git a/doc/user/project/pipelines/img/job_artifacts_browser_button.png b/doc/user/project/pipelines/img/job_artifacts_browser_button.png
new file mode 100644
index 00000000000..21072ce1248
--- /dev/null
+++ b/doc/user/project/pipelines/img/job_artifacts_browser_button.png
Binary files differ
diff --git a/doc/user/project/pipelines/img/job_artifacts_builds_page.png b/doc/user/project/pipelines/img/job_artifacts_builds_page.png
new file mode 100644
index 00000000000..13e039ba934
--- /dev/null
+++ b/doc/user/project/pipelines/img/job_artifacts_builds_page.png
Binary files differ
diff --git a/doc/user/project/pipelines/img/job_artifacts_pipelines_page.png b/doc/user/project/pipelines/img/job_artifacts_pipelines_page.png
new file mode 100644
index 00000000000..3ccce4f9bb4
--- /dev/null
+++ b/doc/user/project/pipelines/img/job_artifacts_pipelines_page.png
Binary files differ
diff --git a/doc/user/project/pipelines/img/job_latest_artifacts_browser.png b/doc/user/project/pipelines/img/job_latest_artifacts_browser.png
new file mode 100644
index 00000000000..c6d8856078b
--- /dev/null
+++ b/doc/user/project/pipelines/img/job_latest_artifacts_browser.png
Binary files differ
diff --git a/doc/user/project/pipelines/img/pipeline_schedules_list.png b/doc/user/project/pipelines/img/pipeline_schedules_list.png
new file mode 100644
index 00000000000..50d9d184b05
--- /dev/null
+++ b/doc/user/project/pipelines/img/pipeline_schedules_list.png
Binary files differ
diff --git a/doc/user/project/pipelines/img/pipeline_schedules_new_form.png b/doc/user/project/pipelines/img/pipeline_schedules_new_form.png
new file mode 100644
index 00000000000..ea5394fa8a6
--- /dev/null
+++ b/doc/user/project/pipelines/img/pipeline_schedules_new_form.png
Binary files differ
diff --git a/doc/user/project/pipelines/img/pipeline_schedules_ownership.png b/doc/user/project/pipelines/img/pipeline_schedules_ownership.png
new file mode 100644
index 00000000000..31ed83abb4d
--- /dev/null
+++ b/doc/user/project/pipelines/img/pipeline_schedules_ownership.png
Binary files differ
diff --git a/doc/user/project/pipelines/img/pipelines_settings_badges.png b/doc/user/project/pipelines/img/pipelines_settings_badges.png
new file mode 100644
index 00000000000..3bdc6374c15
--- /dev/null
+++ b/doc/user/project/pipelines/img/pipelines_settings_badges.png
Binary files differ
diff --git a/doc/user/project/pipelines/img/pipelines_settings_test_coverage.png b/doc/user/project/pipelines/img/pipelines_settings_test_coverage.png
new file mode 100644
index 00000000000..13ed69be810
--- /dev/null
+++ b/doc/user/project/pipelines/img/pipelines_settings_test_coverage.png
Binary files differ
diff --git a/doc/user/project/pipelines/img/pipelines_test_coverage_build.png b/doc/user/project/pipelines/img/pipelines_test_coverage_build.png
new file mode 100644
index 00000000000..7eaba1a256f
--- /dev/null
+++ b/doc/user/project/pipelines/img/pipelines_test_coverage_build.png
Binary files differ
diff --git a/doc/user/project/pipelines/img/pipelines_test_coverage_mr_widget.png b/doc/user/project/pipelines/img/pipelines_test_coverage_mr_widget.png
new file mode 100644
index 00000000000..fbcd612f3f2
--- /dev/null
+++ b/doc/user/project/pipelines/img/pipelines_test_coverage_mr_widget.png
Binary files differ
diff --git a/doc/user/project/pipelines/job_artifacts.md b/doc/user/project/pipelines/job_artifacts.md
new file mode 100644
index 00000000000..e853bfff444
--- /dev/null
+++ b/doc/user/project/pipelines/job_artifacts.md
@@ -0,0 +1,155 @@
+# Introduction to job artifacts
+
+>**Notes:**
+>- Since GitLab 8.2 and GitLab Runner 0.7.0, job artifacts that are created by
+ GitLab Runner are uploaded to GitLab and are downloadable as a single archive
+ (`tar.gz`) using the GitLab UI.
+>- Starting with GitLab 8.4 and GitLab Runner 1.0, the artifacts archive format
+ changed to `ZIP`, and it is now possible to browse its contents, with the added
+ ability of downloading the files separately.
+>- Starting with GitLab 8.17, builds are renamed to jobs.
+>- The artifacts browser will be available only for new artifacts that are sent
+ to GitLab using GitLab Runner version 1.0 and up. It will not be possible to
+ browse old artifacts already uploaded to GitLab.
+>- This is the user documentation. For the administration guide see
+ [administration/job_artifacts](../../../administration/job_artifacts.md).
+
+Artifacts is a list of files and directories which are attached to a job
+after it completes successfully. This feature is enabled by default in all
+GitLab installations.
+
+## Defining artifacts in `.gitlab-ci.yml`
+
+A simple example of using the artifacts definition in `.gitlab-ci.yml` would be
+the following:
+
+```yaml
+pdf:
+ script: xelatex mycv.tex
+ artifacts:
+ paths:
+ - mycv.pdf
+ expire_in: 1 week
+```
+
+A job named `pdf` calls the `xelatex` command in order to build a pdf file from
+the latex source file `mycv.tex`. We then define the `artifacts` paths which in
+turn are defined with the `paths` keyword. All paths to files and directories
+are relative to the repository that was cloned during the build. These uploaded
+artifacts will be kept in GitLab for 1 week as defined by the `expire_in`
+definition. You have the option to keep the artifacts from expiring via the
+[web interface](#browsing-job-artifacts). If you don't define an expiry date,
+the artifacts will be kept forever.
+
+For more examples on artifacts, follow the [artifacts reference in
+`.gitlab-ci.yml`](../../../ci/yaml/README.md#artifacts).
+
+## Browsing job artifacts
+
+>**Note:**
+With GitLab 9.2, PDFs, images, videos and other formats can be previewed
+directly in the job artifacts browser without the need to download them.
+
+After a job finishes, if you visit the job's specific page, there are three
+buttons. You can download the artifacts archive or browse its contents, whereas
+the **Keep** button appears only if you have set an [expiry date] to the
+artifacts in case you changed your mind and want to keep them.
+
+![Job artifacts browser button](img/job_artifacts_browser_button.png)
+
+---
+
+The archive browser shows the name and the actual file size of each file in the
+archive. If your artifacts contained directories, then you are also able to
+browse inside them.
+
+Below you can see how browsing looks like. In this case we have browsed inside
+the archive and at this point there is one directory and one HTML file.
+
+![Job artifacts browser](img/job_artifacts_browser.png)
+
+---
+
+## Downloading job artifacts
+
+If you need to download the whole archive, there are buttons in various places
+inside GitLab that make that possible.
+
+1. While on the pipelines page, you can see the download icon for each job's
+ artifacts archive in the right corner:
+
+ ![Job artifacts in Pipelines page](img/job_artifacts_pipelines_page.png)
+
+1. While on the **Jobs** page, you can see the download icon for each job's
+ artifacts archive in the right corner:
+
+ ![Job artifacts in Builds page](img/job_artifacts_builds_page.png)
+
+1. While inside a specific job, you are presented with a download button
+ along with the one that browses the archive:
+
+ ![Job artifacts browser button](img/job_artifacts_browser_button.png)
+
+1. And finally, when browsing an archive you can see the download button at
+ the top right corner:
+
+ ![Job artifacts browser](img/job_artifacts_browser.png)
+
+## Downloading the latest job artifacts
+
+It is possible to download the latest artifacts of a job via a well known URL
+so you can use it for scripting purposes.
+
+The structure of the URL to download the whole artifacts archive is the following:
+
+```
+https://example.com/<namespace>/<project>/builds/artifacts/<ref>/download?job=<job_name>
+```
+
+To download a single file from the artifacts use the following URL:
+
+```
+https://example.com/<namespace>/<project>/builds/artifacts/<ref>/raw/<path_to_file>?job=<job_name>
+```
+
+For example, to download the latest artifacts of the job named `coverage` of
+the `master` branch of the `gitlab-ce` project that belongs to the `gitlab-org`
+namespace, the URL would be:
+
+```
+https://gitlab.com/gitlab-org/gitlab-ce/builds/artifacts/master/download?job=coverage
+```
+
+To download the file `coverage/index.html` from the same
+artifacts use the following URL:
+
+```
+https://gitlab.com/gitlab-org/gitlab-ce/builds/artifacts/master/raw/coverage/index.html?job=coverage
+```
+
+There is also a URL to browse the latest job artifacts:
+
+```
+https://example.com/<namespace>/<project>/builds/artifacts/<ref>/browse?job=<job_name>
+```
+
+For example:
+
+```
+https://gitlab.com/gitlab-org/gitlab-ce/builds/artifacts/master/browse?job=coverage
+```
+
+The latest builds are also exposed in the UI in various places. Specifically,
+look for the download button in:
+
+- the main project's page
+- the branches page
+- the tags page
+
+If the latest job has failed to upload the artifacts, you can see that
+information in the UI.
+
+![Latest artifacts button](img/job_latest_artifacts_browser.png)
+
+
+[expiry date]: ../../../ci/yaml/README.md#artifacts-expire_in
diff --git a/doc/user/project/pipelines/schedules.md b/doc/user/project/pipelines/schedules.md
new file mode 100644
index 00000000000..17cc21238ff
--- /dev/null
+++ b/doc/user/project/pipelines/schedules.md
@@ -0,0 +1,82 @@
+# Pipeline Schedules
+
+> **Notes**:
+- This feature was introduced in 9.1 as [Trigger Schedule][ce-10533].
+- In 9.2, the feature was [renamed to Pipeline Schedule][ce-10853].
+- Cron notation is parsed by [Rufus-Scheduler](https://github.com/jmettraux/rufus-scheduler).
+
+Pipeline schedules can be used to run pipelines only once, or for example every
+month on the 22nd for a certain branch.
+
+## Using Pipeline schedules
+
+In order to schedule a pipeline:
+
+1. Navigate to your project's **Pipelines ➔ Schedules** and click the
+ **New Schedule** button.
+1. Fill in the form
+1. Hit **Save pipeline schedule** for the changes to take effect.
+
+![New Schedule Form](img/pipeline_schedules_new_form.png)
+
+>**Attention:**
+The pipelines won't be executed precisely, because schedules are handled by
+Sidekiq, which runs according to its interval.
+See [advanced admin configuration](#advanced-admin-configuration) for more
+information.
+
+In the **Schedules** index page you can see a list of the pipelines that are
+scheduled to run. The next run is automatically calculated by the server GitLab
+is installed on.
+
+![Schedules list](img/pipeline_schedules_list.png)
+
+## Using only and except
+
+To configure that a job can be executed only when the pipeline has been
+scheduled (or the opposite), you can use
+[only and except](../../../ci/yaml/README.md#only-and-except) configuration keywords.
+
+```
+job:on-schedule:
+ only:
+ - schedules
+ script:
+ - make world
+
+job:
+ except:
+ - schedules
+ script:
+ - make build
+```
+
+## Taking ownership
+
+Pipelines are executed as a user, who owns a schedule. This influences what
+projects and other resources the pipeline has access to. If a user does not own
+a pipeline, you can take ownership by clicking the **Take ownership** button.
+The next time a pipeline is scheduled, your credentials will be used.
+
+![Schedules list](img/pipeline_schedules_ownership.png)
+
+>**Note:**
+When the owner of the schedule doesn't have the ability to create pipelines
+anymore, due to e.g., being blocked or removed from the project, the schedule
+is deactivated. Another user can take ownership and activate it, so the
+schedule can be run again.
+
+## Advanced admin configuration
+
+The pipelines won't be executed precisely, because schedules are handled by
+Sidekiq, which runs according to its interval. For example, if you set a
+schedule to create a pipeline every minute (`* * * * *`) and the Sidekiq worker
+runs on 00:00 and 12:00 every day (`0 */12 * * *`), only 2 pipelines will be
+created per day. To change the Sidekiq worker's frequency, you have to edit the
+`pipeline_schedule_worker_cron` value in your `gitlab.rb` and restart GitLab.
+For GitLab.com, you can check the [dedicated settings page][settings]. If you
+don't have admin access to the server, ask your administrator.
+
+[ce-10533]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10533
+[ce-10853]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10853
+[settings]: https://about.gitlab.com/gitlab-com/settings/#cron-jobs
diff --git a/doc/user/project/pipelines/settings.md b/doc/user/project/pipelines/settings.md
index 272ee71bfed..435aacd8bb6 100644
--- a/doc/user/project/pipelines/settings.md
+++ b/doc/user/project/pipelines/settings.md
@@ -1,25 +1,39 @@
-# Project Pipeline Settings
+# Pipelines settings
-This section covers project level pipeline settings.
+To reach the pipelines settings navigate to your project's
+**Settings ➔ Pipelines**.
-## Clone vs Fetch
+The following settings can be configured per project.
-You can select to either `git fetch` or `git clone` your project before
-each build. Fetching is faster as you are only pulling recent updates
-but cloning has the advantage of giving you a clean project.
+## Git strategy
+
+With Git strategy, you can choose the default way your repository is fetched
+from GitLab in a job.
+
+There are two options:
+
+- Using `git clone` which is slower since it clones the repository from scratch
+ for every job, ensuring that the project workspace is always pristine.
+- Using `git fetch` which is faster as it re-uses the project workspace (falling
+ back to clone if it doesn't exist).
+
+The default Git strategy can be overridden by the [GIT_STRATEGY variable][var]
+in `.gitlab-ci.yml`.
## Timeout
-This is the total time in minutes that a build is allowed to run. The
-default is 222 minutes.
+Timeout defines the maximum amount of time in minutes that a job is able run.
+The default value is 60 minutes. Decrease the time limit if you want to impose
+a hard limit on your jobs' running time or increase it otherwise. In any case,
+if the job surpasses the threshold, it is marked as failed.
## Custom CI Config File
> - [Introduced][ce-15041] in GitLab 8.13.
By default we look for the `.gitlab-ci.yml` file in the projects root
-directory. If you require a different location **within** the repository
-you can set a custom filepath that will be used to lookup the config file,
+directory. If you require a different location **within** the repository
+you can set a custom filepath that will be used to lookup the config file,
this filepath should be **relative** to the root.
Here are some valid examples:
@@ -29,26 +43,91 @@ Here are some valid examples:
> * my/path/.gitlab-ci.yml
> * my/path/.my-custom-file.yml
-## Test Coverage Parsing
+## Test coverage parsing
+
+If you use test coverage in your code, GitLab can capture its output in the
+job log using a regular expression. In the pipelines settings, search for the
+"Test coverage parsing" section.
+
+![Pipelines settings test coverage](img/pipelines_settings_test_coverage.png)
+
+Leave blank if you want to disable it or enter a ruby regular expression. You
+can use http://rubular.com to test your regex.
+
+If the pipeline succeeds, the coverage is shown in the merge request widget and
+in the jobs table.
+
+![MR widget coverage](img/pipelines_test_coverage_mr_widget.png)
+
+![Build status coverage](img/pipelines_test_coverage_build.png)
+
+A few examples of known coverage tools for a variety of languages can be found
+in the pipelines settings page.
+
+## Visibility of pipelines
+
+For public and internal projects, the pipelines page can be accessed by
+anyone and those logged in respectively. If you wish to hide it so that only
+the members of the project or group have access to it, uncheck the **Public
+pipelines** checkbox and save the changes.
+
+## Auto-cancel pending pipelines
+
+> [Introduced][ce-9362] in GitLab 9.1.
+
+If you want to auto-cancel all pending non-HEAD pipelines on branch, when
+new pipeline will be created (after your git push or manually from UI),
+check **Auto-cancel pending pipelines** checkbox and save the changes.
+
+## Badges
+
+In the pipelines settings page you can find pipeline status and test coverage
+badges for your project. The latest successful pipeline will be used to read
+the pipeline status and test coverage values.
+
+Visit the pipelines settings page in your project to see the exact link to
+your badges, as well as ways to embed the badge image in your HTML or Markdown
+pages.
+
+![Pipelines badges](img/pipelines_settings_badges.png)
+
+### Pipeline status badge
+
+Depending on the status of your job, a badge can have the following values:
+
+- running
+- success
+- failed
+- skipped
+- unknown
+
+You can access a pipeline status badge image using the following link:
-As each testing framework has different output, you need to specify a
-regex to extract the summary code coverage information from your test
-commands output. The regex will be applied to the `STDOUT` of your command.
+```
+https://example.gitlab.com/<namespace>/<project>/badges/<branch>/build.svg
+```
-Here are some examples of popular testing frameworks/languages:
+### Test coverage report badge
-> * Simplecov (Ruby) - `\(\d+.\d+\%\) covered`
-> * pytest-cov (Python) - `\d+\%\s*$`
-> * phpunit --coverage-text --colors=never (PHP) - `^\s*Lines:\s*\d+.\d+\%`
-> * gcovr (C/C++) - `^TOTAL.*\s+(\d+\%)$`
-> * tap --coverage-report=text-summary (Node.js) - `^Statements\s*:\s*([^%]+)`
+GitLab makes it possible to define the regular expression for [coverage report],
+that each job log will be matched against. This means that each job in the
+pipeline can have the test coverage percentage value defined.
+The test coverage badge can be accessed using following link:
-## Public Pipelines
+```
+https://example.gitlab.com/<namespace>/<project>/badges/<branch>/coverage.svg
+```
-You can select if the pipeline should be publicly accessible or not.
+If you would like to get the coverage report from a specific job, you can add
+the `job=coverage_job_name` parameter to the URL. For example, the following
+Markdown code will embed the test coverage report badge of the `coverage` job
+into your `README.md`:
-## Runners Token
+```markdown
+![coverage](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg?job=coverage)
+```
-This is a secure token that is used to checkout the project from the
-Gitlab instance. This should be a cryptographically secure random hash.
+[var]: ../../../ci/yaml/README.md#git-strategy
+[coverage report]: #test-coverage-parsing
+[ce-9362]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9362
diff --git a/doc/user/project/protected_branches.md b/doc/user/project/protected_branches.md
index f7a686d2ccf..0570d9f471f 100644
--- a/doc/user/project/protected_branches.md
+++ b/doc/user/project/protected_branches.md
@@ -27,11 +27,8 @@ See the [Changelog](#changelog) section for changes over time.
To protect a branch, you need to have at least Master permission level. Note
that the `master` branch is protected by default.
-1. Navigate to the main page of the project.
-1. In the upper right corner, click the settings wheel and select **Protected branches**.
-
- ![Project settings list](img/project_settings_list.png)
-
+1. Navigate to your project's **Settings ➔ Repository**
+1. Scroll to find the **Protected branches** section.
1. From the **Branch** dropdown menu, select the branch you want to protect and
click **Protect**. In the screenshot below, we chose the `develop` branch.
@@ -97,8 +94,33 @@ all matching branches:
![Protected branch matches](img/protected_branches_matches.png)
+## Deleting a protected branch
+
+> [Introduced][ce-21393] in GitLab 9.3.
+
+From time to time, it may be required to delete or clean up branches that are
+protected.
+
+User with [Master permissions][perm] and up can manually delete protected
+branches via GitLab's web interface:
+
+1. Visit **Repository > Branches**
+1. Click on the delete icon next to the branch you wish to delete
+1. In order to prevent accidental deletion, an additional confirmation is
+ required
+
+ ![Delete protected branches](img/protected_branches_delete.png)
+
+Deleting a protected branch is only allowed via the web interface, not via Git.
+This means that you can't accidentally delete a protected branch from your
+command line or a Git client application.
+
## Changelog
+**9.2**
+
+- Allow deletion of protected branches via the web interface [gitlab-org/gitlab-ce#21393][ce-21393]
+
**8.11**
- Allow creating protected branches that can't be pushed to [gitlab-org/gitlab-ce!5081][ce-5081]
@@ -113,4 +135,6 @@ all matching branches:
[ce-4665]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4665 "Allow specifying protected branches using wildcards"
[ce-4892]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4892 "Allow developers to merge into a protected branch without having push access"
[ce-5081]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5081 "Allow creating protected branches that can't be pushed to"
+[ce-21393]: https://gitlab.com/gitlab-org/gitlab-ce/issues/21393
[ee-restrict]: http://docs.gitlab.com/ee/user/project/protected_branches.html#restricting-push-and-merge-access-to-certain-users
+[perm]: ../permissions.md
diff --git a/doc/user/project/protected_tags.md b/doc/user/project/protected_tags.md
new file mode 100644
index 00000000000..0cb7aefdb2f
--- /dev/null
+++ b/doc/user/project/protected_tags.md
@@ -0,0 +1,60 @@
+# Protected Tags
+
+> [Introduced][ce-10356] in GitLab 9.1.
+
+Protected Tags allow control over who has permission to create tags as well as preventing accidental update or deletion once created. Each rule allows you to match either an individual tag name, or use wildcards to control multiple tags at once.
+
+This feature evolved out of [Protected Branches](protected_branches.md)
+
+## Overview
+
+Protected tags will prevent anyone from updating or deleting the tag, as and will prevent creation of matching tags based on the permissions you have selected. By default, anyone without Master permission will be prevented from creating tags.
+
+
+## Configuring protected tags
+
+To protect a tag, you need to have at least Master permission level.
+
+1. Navigate to the project's Settings -> Repository page
+
+ ![Repository Settings](img/project_repository_settings.png)
+
+1. From the **Tag** dropdown menu, select the tag you want to protect or type and click `Create wildcard`. In the screenshot below, we chose to protect all tags matching `v*`.
+
+ ![Protected tags page](img/protected_tags_page.png)
+
+1. From the `Allowed to create` dropdown, select who will have permission to create matching tags and then click `Protect`.
+
+ ![Allowed to create tags dropdown](img/protected_tags_permissions_dropdown.png)
+
+1. Once done, the protected tag will appear in the "Protected tags" list.
+
+ ![Protected tags list](img/protected_tags_list.png)
+
+## Wildcard protected tags
+
+You can specify a wildcard protected tag, which will protect all tags
+matching the wildcard. For example:
+
+| Wildcard Protected Tag | Matching Tags |
+|------------------------+-------------------------------|
+| `v*` | `v1.0.0`, `version-9.1` |
+| `*-deploy` | `march-deploy`, `1.0-deploy` |
+| `*gitlab*` | `gitlab`, `gitlab/v1` |
+| `*` | `v1.0.1rc2`, `accidental-tag` |
+
+
+Two different wildcards can potentially match the same tag. For example,
+`*-stable` and `production-*` would both match a `production-stable` tag.
+In that case, if _any_ of these protected tags have a setting like
+"Allowed to create", then `production-stable` will also inherit this setting.
+
+If you click on a protected tag's name, you will be presented with a list of
+all matching tags:
+
+![Protected tag matches](img/protected_tag_matches.png)
+
+
+---
+
+[ce-10356]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10356 "Protected Tags"
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
new file mode 100644
index 00000000000..19b51c83222
--- /dev/null
+++ b/doc/user/project/quick_actions.md
@@ -0,0 +1,39 @@
+# GitLab quick actions
+
+Quick actions are textual shortcuts for common actions on issues or merge
+requests that are usually done by clicking buttons or dropdowns in GitLab's UI.
+You can enter these commands while creating a new issue or merge request, and
+in comments. Each command should be on a separate line in order to be properly
+detected and executed. The commands are removed from the issue, merge request or
+comment body before it is saved and will not be visible to anyone else.
+
+Below is a list of all of the available commands and descriptions about what they
+do.
+
+| Command | Action |
+|:---------------------------|:-------------|
+| `/close` | Close the issue or merge request |
+| `/reopen` | Reopen the issue or merge request |
+| `/merge` | Merge (when pipeline succeeds) |
+| `/title <New title>` | Change title |
+| `/assign @username` | Assign |
+| `/unassign` | Remove assignee |
+| `/milestone %milestone` | Set milestone |
+| `/remove_milestone` | Remove milestone |
+| `/label ~foo ~"bar baz"` | Add label(s) |
+| `/unlabel ~foo ~"bar baz"` | Remove all or specific label(s) |
+| `/relabel ~foo ~"bar baz"` | Replace all label(s) |
+| `/todo` | Add a todo |
+| `/done` | Mark todo as done |
+| `/subscribe` | Subscribe |
+| `/unsubscribe` | Unsubscribe |
+| <code>/due &lt;in 2 days &#124; this Friday &#124; December 31st&gt;</code> | Set due date |
+| `/remove_due_date` | Remove due date |
+| `/wip` | Toggle the Work In Progress status |
+| <code>/estimate &lt;1w 3d 2h 14m&gt;</code> | Set time estimate |
+| `/remove_estimate` | Remove estimated time |
+| <code>/spend &lt;1h 30m &#124; -1h 5m&gt;</code> | Add or subtract spent time |
+| `/remove_time_spent` | Remove time spent |
+| `/target_branch <Branch Name>` | Set target branch for current merge request |
+| `/award :emoji:` | Toggle award for :emoji: |
+| `/board_move ~column` | Move issue to column on the board |
diff --git a/doc/user/project/repository/branches/img/delete_merged_branches.png b/doc/user/project/repository/branches/img/delete_merged_branches.png
new file mode 100644
index 00000000000..1856a624f74
--- /dev/null
+++ b/doc/user/project/repository/branches/img/delete_merged_branches.png
Binary files differ
diff --git a/doc/user/project/repository/branches/index.md b/doc/user/project/repository/branches/index.md
new file mode 100644
index 00000000000..1948627ee79
--- /dev/null
+++ b/doc/user/project/repository/branches/index.md
@@ -0,0 +1,17 @@
+# Branches
+
+## Delete merged branches
+
+> [Introduced][ce-6449] in GitLab 8.14.
+
+![Delete merged branches](img/delete_merged_branches.png)
+
+This feature allows merged branches to be deleted in bulk. Only branches that
+have been merged and [are not protected][protected] will be deleted as part of
+this operation.
+
+It's particularly useful to clean up old branches that were not deleting
+automatically when a merge request was merged.
+
+[ce-6449]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6449 "Add button to delete all merged branches"
+[protected]: ../../protected_branches.md
diff --git a/doc/user/project/repository/img/web_editor_new_branch_dropdown.png b/doc/user/project/repository/img/web_editor_new_branch_dropdown.png
index a8e635d2faf..31edb6bde3a 100644
--- a/doc/user/project/repository/img/web_editor_new_branch_dropdown.png
+++ b/doc/user/project/repository/img/web_editor_new_branch_dropdown.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_new_branch_from_issue.png b/doc/user/project/repository/img/web_editor_new_branch_from_issue.png
new file mode 100644
index 00000000000..4729f5383c0
--- /dev/null
+++ b/doc/user/project/repository/img/web_editor_new_branch_from_issue.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_new_branch_page.png b/doc/user/project/repository/img/web_editor_new_branch_page.png
index 7f36b7faf63..8d82f981527 100644
--- a/doc/user/project/repository/img/web_editor_new_branch_page.png
+++ b/doc/user/project/repository/img/web_editor_new_branch_page.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_new_directory_dialog.png b/doc/user/project/repository/img/web_editor_new_directory_dialog.png
index d16e3c67116..1c9beff8849 100644
--- a/doc/user/project/repository/img/web_editor_new_directory_dialog.png
+++ b/doc/user/project/repository/img/web_editor_new_directory_dialog.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_new_directory_dropdown.png b/doc/user/project/repository/img/web_editor_new_directory_dropdown.png
index c8d77b16ee8..ede691f6f74 100644
--- a/doc/user/project/repository/img/web_editor_new_directory_dropdown.png
+++ b/doc/user/project/repository/img/web_editor_new_directory_dropdown.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_new_file_dropdown.png b/doc/user/project/repository/img/web_editor_new_file_dropdown.png
index 3fcb91c9b93..13a4d721039 100644
--- a/doc/user/project/repository/img/web_editor_new_file_dropdown.png
+++ b/doc/user/project/repository/img/web_editor_new_file_dropdown.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_new_file_editor.png b/doc/user/project/repository/img/web_editor_new_file_editor.png
index 21c340b9288..d0bcc69bf63 100644
--- a/doc/user/project/repository/img/web_editor_new_file_editor.png
+++ b/doc/user/project/repository/img/web_editor_new_file_editor.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_new_push_widget.png b/doc/user/project/repository/img/web_editor_new_push_widget.png
index c7738a4c930..77756876d4f 100644
--- a/doc/user/project/repository/img/web_editor_new_push_widget.png
+++ b/doc/user/project/repository/img/web_editor_new_push_widget.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_new_tag_dropdown.png b/doc/user/project/repository/img/web_editor_new_tag_dropdown.png
index ac7415009b3..b52d5cabdf2 100644
--- a/doc/user/project/repository/img/web_editor_new_tag_dropdown.png
+++ b/doc/user/project/repository/img/web_editor_new_tag_dropdown.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_new_tag_page.png b/doc/user/project/repository/img/web_editor_new_tag_page.png
index 231e1a13fc0..d6d9945397c 100644
--- a/doc/user/project/repository/img/web_editor_new_tag_page.png
+++ b/doc/user/project/repository/img/web_editor_new_tag_page.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_start_new_merge_request.png b/doc/user/project/repository/img/web_editor_start_new_merge_request.png
index 2755501dfd1..384e8320f15 100644
--- a/doc/user/project/repository/img/web_editor_start_new_merge_request.png
+++ b/doc/user/project/repository/img/web_editor_start_new_merge_request.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_template_dropdown_buttons.png b/doc/user/project/repository/img/web_editor_template_dropdown_buttons.png
index 4efc51cc423..f21183125f6 100644
--- a/doc/user/project/repository/img/web_editor_template_dropdown_buttons.png
+++ b/doc/user/project/repository/img/web_editor_template_dropdown_buttons.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_template_dropdown_first_file.png b/doc/user/project/repository/img/web_editor_template_dropdown_first_file.png
index 67190c58823..7f31c2a8887 100644
--- a/doc/user/project/repository/img/web_editor_template_dropdown_first_file.png
+++ b/doc/user/project/repository/img/web_editor_template_dropdown_first_file.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_template_dropdown_mit_license.png b/doc/user/project/repository/img/web_editor_template_dropdown_mit_license.png
index 47719113805..afd44d78959 100644
--- a/doc/user/project/repository/img/web_editor_template_dropdown_mit_license.png
+++ b/doc/user/project/repository/img/web_editor_template_dropdown_mit_license.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_upload_file_dialog.png b/doc/user/project/repository/img/web_editor_upload_file_dialog.png
index 9d6d8250bbe..04e951406ad 100644
--- a/doc/user/project/repository/img/web_editor_upload_file_dialog.png
+++ b/doc/user/project/repository/img/web_editor_upload_file_dialog.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_upload_file_dropdown.png b/doc/user/project/repository/img/web_editor_upload_file_dropdown.png
index 6b5205b05ec..b8c766d4b99 100644
--- a/doc/user/project/repository/img/web_editor_upload_file_dropdown.png
+++ b/doc/user/project/repository/img/web_editor_upload_file_dropdown.png
Binary files differ
diff --git a/doc/user/project/repository/web_editor.md b/doc/user/project/repository/web_editor.md
index 993c6bfb7e9..d47a3acdbe9 100644
--- a/doc/user/project/repository/web_editor.md
+++ b/doc/user/project/repository/web_editor.md
@@ -97,11 +97,11 @@ There are multiple ways to create a branch from GitLab's web interface.
In case your development workflow dictates to have an issue for every merge
request, you can quickly create a branch right on the issue page which will be
-tied with the issue itself. You can see a **New Branch** button after the issue
+tied with the issue itself. You can see a **New branch** button after the issue
description, unless there is already a branch with the same name or a referenced
merge request.
-![New Branch Button](img/new_branch_from_issue.png)
+![New Branch Button](img/web_editor_new_branch_from_issue.png)
Once you click it, a new branch will be created that diverges from the default
branch of your project, by default `master`. The branch name will be based on
@@ -109,12 +109,19 @@ the title of the issue and as suffix it will have its ID. Thus, the example
screenshot above will yield a branch named
`2-et-cum-et-sed-expedita-repellat-consequatur-ut-assumenda-numquam-rerum`.
+Since GitLab 9.0, when you click the `New branch` in an empty repository project, GitLab automatically creates the master branch, commits a blank `README.md` file to it and creates and redirects you to a new branch based on the issue title.
+If your [project is already configured with a deployment service][project-services-doc] (e.g. Kubernetes), GitLab takes one step further and prompts you to set up [auto deploy][auto-deploy-doc] by helping you create a `.gitlab-ci.yml` file.
+
+
After the branch is created, you can edit files in the repository to fix
the issue. When a merge request is created based on the newly created branch,
the description field will automatically display the [issue closing pattern]
`Closes #ID`, where `ID` the ID of the issue. This will close the issue once the
merge request is merged.
+[project-services-doc]: ../integrations/project_services.md
+[auto-deploy-doc]: ../../../ci/autodeploy/index.md
+
### Create a new branch from a project's dashboard
If you want to make changes to several files before creating a new merge
@@ -170,6 +177,5 @@ you commit the changes you will be taken to a new merge request form.
![Start a new merge request with these changes](img/web_editor_start_new_merge_request.png)
-![New file button](basicsimages/file_button.png)
[ce-2808]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2808
-[issue closing pattern]: ../user/project/issues/automatic_issue_closing.md
+[issue closing pattern]: ../issues/automatic_issue_closing.md
diff --git a/doc/user/project/settings/img/import_export_download_export.png b/doc/user/project/settings/img/import_export_download_export.png
index a2f7f0085c1..4945590e3e8 100644
--- a/doc/user/project/settings/img/import_export_download_export.png
+++ b/doc/user/project/settings/img/import_export_download_export.png
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_export_button.png b/doc/user/project/settings/img/import_export_export_button.png
index 1f7bdd21b0d..eef79821f8b 100644
--- a/doc/user/project/settings/img/import_export_export_button.png
+++ b/doc/user/project/settings/img/import_export_export_button.png
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_mail_link.png b/doc/user/project/settings/img/import_export_mail_link.png
index c123f83eb8e..48ef42855bc 100644
--- a/doc/user/project/settings/img/import_export_mail_link.png
+++ b/doc/user/project/settings/img/import_export_mail_link.png
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_new_project.png b/doc/user/project/settings/img/import_export_new_project.png
index b3a7f201018..9dd509dc4a0 100644
--- a/doc/user/project/settings/img/import_export_new_project.png
+++ b/doc/user/project/settings/img/import_export_new_project.png
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_select_file.png b/doc/user/project/settings/img/import_export_select_file.png
index f31832af3e1..fb831dca32b 100644
--- a/doc/user/project/settings/img/import_export_select_file.png
+++ b/doc/user/project/settings/img/import_export_select_file.png
Binary files differ
diff --git a/doc/user/project/settings/img/settings_edit_button.png b/doc/user/project/settings/img/settings_edit_button.png
index 3c0cee536de..9f3a8330e3a 100644
--- a/doc/user/project/settings/img/settings_edit_button.png
+++ b/doc/user/project/settings/img/settings_edit_button.png
Binary files differ
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index 65ed9fae4ec..35960ade3d4 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -14,6 +14,11 @@
> raketask.
> - The exports are stored in a temporary [shared directory][tmp] and are deleted
> every 24 hours by a specific worker.
+> - Group members will get exported as project members, as long as the user has
+> master or admin access to the group where the exported project lives. An admin
+> in the import side is required to map the users, based on email or username.
+> Otherwise, a supplementary comment is left to mention the original author and
+> the MRs, notes or issues will be owned by the importer.
Existing projects running on any GitLab instance or GitLab.com can be exported
with all their related data and be moved into a new GitLab instance.
@@ -22,12 +27,16 @@ with all their related data and be moved into a new GitLab instance.
| GitLab version | Import/Export version |
| -------- | -------- |
-| 8.12.0 to current | 0.1.4 |
-| 8.10.3 | 0.1.3 |
-| 8.10.0 | 0.1.2 |
-| 8.9.5 | 0.1.1 |
-| 8.9.0 | 0.1.0 |
-
+| 9.4.0 to current | 0.1.8 |
+| 9.2.0 | 0.1.7 |
+| 8.17.0 | 0.1.6 |
+| 8.13.0 | 0.1.5 |
+| 8.12.0 | 0.1.4 |
+| 8.10.3 | 0.1.3 |
+| 8.10.0 | 0.1.2 |
+| 8.9.5 | 0.1.1 |
+| 8.9.0 | 0.1.0 |
+
> The table reflects what GitLab version we updated the Import/Export version at.
> For instance, 8.10.3 and 8.11 will have the same Import/Export version (0.1.3)
> and the exports between them will be compatible.
@@ -46,6 +55,9 @@ The following items will NOT be exported:
- Build traces and artifacts
- LFS objects
+- Container registry images
+- CI variables
+- Any encrypted tokens
## Exporting a project and its data
diff --git a/doc/user/project/slash_commands.md b/doc/user/project/slash_commands.md
index 5f6a6c6503e..e9103a3f49c 100644
--- a/doc/user/project/slash_commands.md
+++ b/doc/user/project/slash_commands.md
@@ -1,31 +1 @@
-# GitLab slash commands
-
-Slash commands are textual shortcuts for common actions on issues or merge
-requests that are usually done by clicking buttons or dropdowns in GitLab's UI.
-You can enter these commands while creating a new issue or merge request, and
-in comments. Each command should be on a separate line in order to be properly
-detected and executed. The commands are removed from the issue, merge request or
-comment body before it is saved and will not be visible to anyone else.
-
-Below is a list of all of the available commands and descriptions about what they
-do.
-
-| Command | Action |
-|:---------------------------|:-------------|
-| `/close` | Close the issue or merge request |
-| `/reopen` | Reopen the issue or merge request |
-| `/title <New title>` | Change title |
-| `/assign @username` | Assign |
-| `/unassign` | Remove assignee |
-| `/milestone %milestone` | Set milestone |
-| `/remove_milestone` | Remove milestone |
-| `/label ~foo ~"bar baz"` | Add label(s) |
-| `/unlabel ~foo ~"bar baz"` | Remove all or specific label(s) |
-| `/relabel ~foo ~"bar baz"` | Replace all label(s) |
-| `/todo` | Add a todo |
-| `/done` | Mark todo as done |
-| `/subscribe` | Subscribe |
-| `/unsubscribe` | Unsubscribe |
-| <code>/due &lt;in 2 days &#124; this Friday &#124; December 31st&gt;</code> | Set due date |
-| `/remove_due_date` | Remove due date |
-| `/wip` | Toggle the Work In Progress status |
+This document was moved to [user/project/quick_actions.md](quick_actions.md).
diff --git a/doc/user/project/wiki/img/wiki_create_home_page.png b/doc/user/project/wiki/img/wiki_create_home_page.png
new file mode 100644
index 00000000000..f50f564034c
--- /dev/null
+++ b/doc/user/project/wiki/img/wiki_create_home_page.png
Binary files differ
diff --git a/doc/user/project/wiki/img/wiki_create_new_page.png b/doc/user/project/wiki/img/wiki_create_new_page.png
new file mode 100644
index 00000000000..c19124a8923
--- /dev/null
+++ b/doc/user/project/wiki/img/wiki_create_new_page.png
Binary files differ
diff --git a/doc/user/project/wiki/img/wiki_create_new_page_modal.png b/doc/user/project/wiki/img/wiki_create_new_page_modal.png
new file mode 100644
index 00000000000..ece437967dc
--- /dev/null
+++ b/doc/user/project/wiki/img/wiki_create_new_page_modal.png
Binary files differ
diff --git a/doc/user/project/wiki/img/wiki_page_history.png b/doc/user/project/wiki/img/wiki_page_history.png
new file mode 100644
index 00000000000..0e6af1b468d
--- /dev/null
+++ b/doc/user/project/wiki/img/wiki_page_history.png
Binary files differ
diff --git a/doc/user/project/wiki/img/wiki_sidebar.png b/doc/user/project/wiki/img/wiki_sidebar.png
new file mode 100644
index 00000000000..59814e2a06e
--- /dev/null
+++ b/doc/user/project/wiki/img/wiki_sidebar.png
Binary files differ
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
new file mode 100644
index 00000000000..e9ee1abc6c1
--- /dev/null
+++ b/doc/user/project/wiki/index.md
@@ -0,0 +1,97 @@
+# Wiki
+
+A separate system for documentation called Wiki, is built right into each
+GitLab project. It is enabled by default on all new projects and you can find
+it under **Wiki** in your project.
+
+Wikis are very convenient if you don't want to keep you documentation in your
+repository, but you do want to keep it in the same project where your code
+resides.
+
+You can create Wiki pages in the web interface or
+[locally using Git](#adding-and-editing-wiki-pages-locally) since every Wiki is
+a separate Git repository.
+
+>**Note:**
+A [permission level][permissions] of **Guest** is needed to view a Wiki and
+**Developer** is needed to create and edit Wiki pages.
+
+## First time creating the Home page
+
+The first time you visit a Wiki, you will be directed to create the Home page.
+The Home page is necessary to be created since it serves as the landing page
+when viewing a Wiki. You only have to fill in the **Content** section and click
+**Create page**. You can always edit it later, so go ahead and write a welcome
+message.
+
+![New home page](img/wiki_create_home_page.png)
+
+## Creating a new wiki page
+
+Create a new page by clicking the **New page** button that can be found
+in all wiki pages. You will be asked to fill in the page name from which GitLab
+will create the path to the page. You can specify a full path for the new file
+and any missing directories will be created automatically.
+
+![New page modal](img/wiki_create_new_page_modal.png)
+
+Once you enter the page name, it's time to fill in its content. GitLab wikis
+support Markdown, RDoc and AsciiDoc. For Markdown based pages, all the
+[Markdown features](../../markdown.md) are supported and for links there is
+some [wiki specific](../../markdown.md#wiki-specific-markdown) behavior.
+
+>**Note:**
+The wiki is based on a Git repository and contains only text files. Uploading
+files via the web interface will upload them in GitLab itself, and they will
+not be available if you clone the wiki repo locally.
+
+In the web interface the commit message is optional, but the GitLab Wiki is
+based on Git and needs a commit message, so one will be created for you if you
+do not enter one.
+
+When you're ready, click the **Create page** and the new page will be created.
+
+![New page](img/wiki_create_new_page.png)
+
+## Editing a wiki page
+
+To edit a page, simply click on the **Edit** button. From there on, you can
+change its content. When done, click **Save changes** for the changes to take
+effect.
+
+## Deleting a wiki page
+
+You can find the **Delete** button only when editing a page. Click on it and
+confirm you want the page to be deleted.
+
+## Viewing a list of all created wiki pages
+
+Every wiki has a sidebar from which a short list of the created pages can be
+found. The list is ordered alphabetically.
+
+![Wiki sidebar](img/wiki_sidebar.png)
+
+If you have many pages, not all will be listed in the sidebar. Click on
+**More pages** to see all of them.
+
+## Viewing the history of a wiki page
+
+The changes of a wiki page over time are recorded in the wiki's Git repository,
+and you can view them by clicking the **Page history** button.
+
+From the history page you can see the revision of the page (Git commit SHA), its
+author, the commit message, when it was last updated and the page markup format.
+To see how a previous version of the page looked like, click on a revision
+number.
+
+![Wiki page history](img/wiki_page_history.png)
+
+## Adding and editing wiki pages locally
+
+Since wikis are based on Git repositories, you can clone them locally and edit
+them like you would do with every other Git repository.
+
+On the right sidebar, click on **Clone repository** and follow the on-screen
+instructions.
+
+[permissions]: ../../permissions.md
diff --git a/doc/user/search/img/issue_search_filter.png b/doc/user/search/img/issue_search_filter.png
new file mode 100644
index 00000000000..f357abd6bac
--- /dev/null
+++ b/doc/user/search/img/issue_search_filter.png
Binary files differ
diff --git a/doc/user/search/img/issues_any_assignee.png b/doc/user/search/img/issues_any_assignee.png
new file mode 100755
index 00000000000..2f902bcc66c
--- /dev/null
+++ b/doc/user/search/img/issues_any_assignee.png
Binary files differ
diff --git a/doc/user/search/img/issues_assigned_to_you.png b/doc/user/search/img/issues_assigned_to_you.png
new file mode 100755
index 00000000000..36c670eedd5
--- /dev/null
+++ b/doc/user/search/img/issues_assigned_to_you.png
Binary files differ
diff --git a/doc/user/search/img/issues_author.png b/doc/user/search/img/issues_author.png
new file mode 100755
index 00000000000..792f9746db6
--- /dev/null
+++ b/doc/user/search/img/issues_author.png
Binary files differ
diff --git a/doc/user/search/img/issues_mrs_shortcut.png b/doc/user/search/img/issues_mrs_shortcut.png
new file mode 100755
index 00000000000..6380b337b54
--- /dev/null
+++ b/doc/user/search/img/issues_mrs_shortcut.png
Binary files differ
diff --git a/doc/user/search/img/left_menu_bar.png b/doc/user/search/img/left_menu_bar.png
new file mode 100755
index 00000000000..d68a71cba8e
--- /dev/null
+++ b/doc/user/search/img/left_menu_bar.png
Binary files differ
diff --git a/doc/user/search/img/project_search.png b/doc/user/search/img/project_search.png
new file mode 100755
index 00000000000..3150b40de29
--- /dev/null
+++ b/doc/user/search/img/project_search.png
Binary files differ
diff --git a/doc/user/search/img/search_history.gif b/doc/user/search/img/search_history.gif
new file mode 100644
index 00000000000..4cfa48ee0ab
--- /dev/null
+++ b/doc/user/search/img/search_history.gif
Binary files differ
diff --git a/doc/user/search/img/search_issues_board.png b/doc/user/search/img/search_issues_board.png
new file mode 100755
index 00000000000..84048ae6a02
--- /dev/null
+++ b/doc/user/search/img/search_issues_board.png
Binary files differ
diff --git a/doc/user/search/img/sort_projects.png b/doc/user/search/img/sort_projects.png
new file mode 100755
index 00000000000..9bf2770b299
--- /dev/null
+++ b/doc/user/search/img/sort_projects.png
Binary files differ
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
new file mode 100644
index 00000000000..6d59dcc6c75
--- /dev/null
+++ b/doc/user/search/index.md
@@ -0,0 +1,104 @@
+# Search through GitLab
+
+## Issues and merge requests
+
+To search through issues and merge requests in multiple projects, you can use the left-sidebar.
+
+Click the menu bar, then **Issues** or **Merge Requests**, which work in the same way,
+therefore, the following notes are valid for both.
+
+The number displayed on their right represents the number of issues and merge requests assigned to you.
+
+![menu bar - issues and MRs assigned to you](img/left_menu_bar.png)
+
+When you click **Issues**, you'll see the opened issues assigned to you straight away:
+
+![Issues assigned to you](img/issues_assigned_to_you.png)
+
+You can filter them by **Author**, **Assignee**, **Milestone**, and **Labels**,
+searching through **Open**, **Closed**, and **All** issues.
+
+Of course, you can combine all filters together.
+
+### Issues and MRs assigned to you or created by you
+
+You'll find a shortcut to issues and merge requests create by you or assigned to you
+on the search field on the top-right of your screen:
+
+![shortcut to your issues and mrs](img/issues_mrs_shortcut.png)
+
+## Issues and merge requests per project
+
+If you want to search for issues present in a specific project, navigate to
+a project's **Issues** tab, and click on the field **Search or filter results...**. It will
+display a dropdown menu, from which you can add filters per author, assignee, milestone, label,
+and weight. When done, press **Enter** on your keyboard to filter the issues.
+
+![filter issues in a project](img/issue_search_filter.png)
+
+The same process is valid for merge requests. Navigate to your project's **Merge Requests** tab,
+and click **Search or filter results...**. Merge requests can be filtered by author, assignee,
+milestone, and label.
+
+## Search history
+
+You can view recent searches by clicking on the little arrow-clock icon, which is to the left of the search input. Click the search entry to run that search again. This feature is available for issues and merge requests. Searches are stored locally in your browser.
+
+![search history](img/search_history.gif)
+
+## Removing search filters
+
+Individual filters can be removed by clicking on the filter's (x) button or backspacing. The entire search filter can be cleared by clicking on the search box's (x) button.
+
+### Shortcut
+
+You'll also find a shortcut on the search field on the top-right of the project's dashboard to
+quickly access issues and merge requests created or assigned to you within that project:
+
+![search per project - shortcut](img/project_search.png)
+
+## Todos
+
+Your [todos](../../workflow/todos.md#gitlab-todos) can be searched by "to do" and "done".
+You can [filter](../../workflow/todos.md#filtering-your-todos) them per project,
+author, type, and action. Also, you can sort them by
+[**Label priority**](../../user/project/labels.md#prioritize-labels),
+**Last created** and **Oldest created**.
+
+## Projects
+
+You can search through your projects from the left menu, by clicking the menu bar, then **Projects**.
+On the field **Filter by name**, type the project or group name you want to find, and GitLab
+will filter them for you as you type.
+
+You can also look for the projects you starred (**Starred projects**), and **Explore** all
+public and internal projects available in GitLab.com, from which you can filter by visibitily,
+through **Trending**, best rated with **Most starts**, or **All** of them.
+
+You can also sort them by **Name**, **Last created**, **Oldest created**, **Last updated**,
+**Oldest updated**, **Owner**, and choose to hide or show **archived projects**:
+
+![sort projects](img/sort_projects.png)
+
+## Groups
+
+Similarly to [projects search](#projects), you can search through your groups from
+the left menu, by clicking the menu bar, then **Groups**.
+
+On the field **Filter by name**, type the group name you want to find, and GitLab
+will filter them for you as you type.
+
+You can also **Explore** all public and internal groups available in GitLab.com,
+and sort them by **Last created**, **Oldest created**, **Last updated**, or **Oldest updated**.
+
+## Issue Boards
+
+From an [Issue Board](../../user/project/issue_board.md), you can filter issues by **Author**, **Assignee**, **Milestone**, and **Labels**.
+You can also filter them by name (issue title), from the field **Filter by name**, which is loaded as you type.
+
+When you want to search for issues to add to lists present in your Issue Board, click
+the button **Add issues** on the top-right of your screen, opening a modal window from which
+you'll be able to, besides filtering them by **Name**, **Author**, **Assignee**, **Milestone**,
+and **Labels**, select multiple issues to add to a list of your choice:
+
+![search and select issues to add to board](img/search_issues_board.png)
diff --git a/doc/user/snippets.md b/doc/user/snippets.md
new file mode 100644
index 00000000000..78861625f8a
--- /dev/null
+++ b/doc/user/snippets.md
@@ -0,0 +1,29 @@
+# Snippets
+
+Snippets are little bits of code or text.
+
+![GitLab Snippet](img/gitlab_snippet.png)
+
+There are 2 types of snippets - project snippets and personal snippets.
+
+## Comments
+
+With GitLab Snippets you engage in a conversation about that piece of code,
+facilitating the collaboration among users.
+
+> **Note:**
+Comments on snippets was [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/12910) in [GitLab Community Edition 9.2](https://about.gitlab.com/2017/05/22/gitlab-9-2-released/#comments-for-personal-snippets).
+
+## Project snippets
+
+Project snippets are always related to a specific project - see [Project features](../workflow/project_features.md) for more information.
+
+## Personal snippets
+
+Personal snippets are not related to any project and can be created completely independently. There are 3 visibility levels that can be set (public, internal, private - see [Public Access](../public_access/public_access.md) for more information).
+
+## Downloading snippets
+
+You can download the raw content of a snippet.
+
+By default snippets will be downloaded with Linux-style line endings (`LF`). If you want to preserve the original line endings you need to add a parameter `line_ending=raw` (eg. `https://gitlab.com/snippets/SNIPPET_ID/raw?line_ending=raw`). In case a snippet was created using the GitLab web interface the original line ending is Windows-like (`CRLF`).
diff --git a/doc/web_hooks/ssl.png b/doc/web_hooks/ssl.png
deleted file mode 100644
index 8c4f08d1825..00000000000
--- a/doc/web_hooks/ssl.png
+++ /dev/null
Binary files differ
diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md
index 33c1a79d59c..0ebe5eea173 100644
--- a/doc/web_hooks/web_hooks.md
+++ b/doc/web_hooks/web_hooks.md
@@ -1,956 +1 @@
-# Webhooks
-
-_**Note:**
-Starting from GitLab 8.5:_
-
-- _the `repository` key is deprecated in favor of the `project` key_
-- _the `project.ssh_url` key is deprecated in favor of the `project.git_ssh_url` key_
-- _the `project.http_url` key is deprecated in favor of the `project.git_http_url` key_
-
-Project webhooks allow you to trigger an URL if new code is pushed or a new issue is created.
-
-You can configure webhooks to listen for specific events like pushes, issues or merge requests. GitLab will send a POST request with data to the webhook URL.
-
-Webhooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server.
-
-## Webhook endpoint tips
-
-If you are writing your own endpoint (web server) that will receive
-GitLab webhooks keep in mind the following things:
-
-- Your endpoint should send its HTTP response as fast as possible. If
- you wait too long, GitLab may decide the hook failed and retry it.
-- Your endpoint should ALWAYS return a valid HTTP response. If you do
- not do this then GitLab will think the hook failed and retry it.
- Most HTTP libraries take care of this for you automatically but if
- you are writing a low-level hook this is important to remember.
-- GitLab ignores the HTTP status code returned by your endpoint.
-
-## Secret Token
-
-If you specify a secret token, it will be sent with the hook request in the `X-Gitlab-Token` HTTP header. Your webhook endpoint can check that to verify that the request is legitimate.
-
-## SSL Verification
-
-By default, the SSL certificate of the webhook endpoint is verified based on
-an internal list of Certificate Authorities,
-which means the certificate cannot be self-signed.
-
-You can turn this off in the webhook settings in your GitLab projects.
-
-![SSL Verification](ssl.png)
-
-## Push events
-
-Triggered when you push to the repository except when pushing tags.
-
-**Request header**:
-
-```
-X-Gitlab-Event: Push Hook
-```
-
-**Request body:**
-
-```json
-{
- "object_kind": "push",
- "before": "95790bf891e76fee5e1747ab589903a6a1f80f22",
- "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
- "ref": "refs/heads/master",
- "checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
- "user_id": 4,
- "user_name": "John Smith",
- "user_email": "john@example.com",
- "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
- "project_id": 15,
- "project":{
- "name":"Diaspora",
- "description":"",
- "web_url":"http://example.com/mike/diaspora",
- "avatar_url":null,
- "git_ssh_url":"git@example.com:mike/diaspora.git",
- "git_http_url":"http://example.com/mike/diaspora.git",
- "namespace":"Mike",
- "visibility_level":0,
- "path_with_namespace":"mike/diaspora",
- "default_branch":"master",
- "homepage":"http://example.com/mike/diaspora",
- "url":"git@example.com:mike/diaspora.git",
- "ssh_url":"git@example.com:mike/diaspora.git",
- "http_url":"http://example.com/mike/diaspora.git"
- },
- "repository":{
- "name": "Diaspora",
- "url": "git@example.com:mike/diaspora.git",
- "description": "",
- "homepage": "http://example.com/mike/diaspora",
- "git_http_url":"http://example.com/mike/diaspora.git",
- "git_ssh_url":"git@example.com:mike/diaspora.git",
- "visibility_level":0
- },
- "commits": [
- {
- "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
- "message": "Update Catalan translation to e38cb41.",
- "timestamp": "2011-12-12T14:27:31+02:00",
- "url": "http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
- "author": {
- "name": "Jordi Mallach",
- "email": "jordi@softcatala.org"
- },
- "added": ["CHANGELOG"],
- "modified": ["app/controller/application.rb"],
- "removed": []
- },
- {
- "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
- "message": "fixed readme",
- "timestamp": "2012-01-03T23:36:29+02:00",
- "url": "http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
- "author": {
- "name": "GitLab dev user",
- "email": "gitlabdev@dv6700.(none)"
- },
- "added": ["CHANGELOG"],
- "modified": ["app/controller/application.rb"],
- "removed": []
- }
- ],
- "total_commits_count": 4
-}
-```
-
-## Tag events
-
-Triggered when you create (or delete) tags to the repository.
-
-**Request header**:
-
-```
-X-Gitlab-Event: Tag Push Hook
-```
-
-**Request body:**
-
-```json
-{
- "object_kind": "tag_push",
- "before": "0000000000000000000000000000000000000000",
- "after": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7",
- "ref": "refs/tags/v1.0.0",
- "checkout_sha": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7",
- "user_id": 1,
- "user_name": "John Smith",
- "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
- "project_id": 1,
- "project":{
- "name":"Example",
- "description":"",
- "web_url":"http://example.com/jsmith/example",
- "avatar_url":null,
- "git_ssh_url":"git@example.com:jsmith/example.git",
- "git_http_url":"http://example.com/jsmith/example.git",
- "namespace":"Jsmith",
- "visibility_level":0,
- "path_with_namespace":"jsmith/example",
- "default_branch":"master",
- "homepage":"http://example.com/jsmith/example",
- "url":"git@example.com:jsmith/example.git",
- "ssh_url":"git@example.com:jsmith/example.git",
- "http_url":"http://example.com/jsmith/example.git"
- },
- "repository":{
- "name": "Example",
- "url": "ssh://git@example.com/jsmith/example.git",
- "description": "",
- "homepage": "http://example.com/jsmith/example",
- "git_http_url":"http://example.com/jsmith/example.git",
- "git_ssh_url":"git@example.com:jsmith/example.git",
- "visibility_level":0
- },
- "commits": [],
- "total_commits_count": 0
-}
-```
-
-## Issues events
-
-Triggered when a new issue is created or an existing issue was updated/closed/reopened.
-
-**Request header**:
-
-```
-X-Gitlab-Event: Issue Hook
-```
-
-**Request body:**
-
-```json
-{
- "object_kind": "issue",
- "user": {
- "name": "Administrator",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
- },
- "project":{
- "name":"Gitlab Test",
- "description":"Aut reprehenderit ut est.",
- "web_url":"http://example.com/gitlabhq/gitlab-test",
- "avatar_url":null,
- "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git",
- "git_http_url":"http://example.com/gitlabhq/gitlab-test.git",
- "namespace":"GitlabHQ",
- "visibility_level":20,
- "path_with_namespace":"gitlabhq/gitlab-test",
- "default_branch":"master",
- "homepage":"http://example.com/gitlabhq/gitlab-test",
- "url":"http://example.com/gitlabhq/gitlab-test.git",
- "ssh_url":"git@example.com:gitlabhq/gitlab-test.git",
- "http_url":"http://example.com/gitlabhq/gitlab-test.git"
- },
- "repository":{
- "name": "Gitlab Test",
- "url": "http://example.com/gitlabhq/gitlab-test.git",
- "description": "Aut reprehenderit ut est.",
- "homepage": "http://example.com/gitlabhq/gitlab-test"
- },
- "object_attributes": {
- "id": 301,
- "title": "New API: create/update/delete file",
- "assignee_id": 51,
- "author_id": 51,
- "project_id": 14,
- "created_at": "2013-12-03T17:15:43Z",
- "updated_at": "2013-12-03T17:15:43Z",
- "position": 0,
- "branch_name": null,
- "description": "Create new API for manipulations with repository",
- "milestone_id": null,
- "state": "opened",
- "iid": 23,
- "url": "http://example.com/diaspora/issues/23",
- "action": "open"
- },
- "assignee": {
- "name": "User1",
- "username": "user1",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
- }
-}
-```
-## Comment events
-
-Triggered when a new comment is made on commits, merge requests, issues, and code snippets.
-The note data will be stored in `object_attributes` (e.g. `note`, `noteable_type`). The
-payload will also include information about the target of the comment. For example,
-a comment on a issue will include the specific issue information under the `issue` key.
-Valid target types:
-
-1. `commit`
-2. `merge_request`
-3. `issue`
-4. `snippet`
-
-### Comment on commit
-
-**Request header**:
-
-```
-X-Gitlab-Event: Note Hook
-```
-
-**Request body:**
-
-```json
-{
- "object_kind": "note",
- "user": {
- "name": "Administrator",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
- },
- "project_id": 5,
- "project":{
- "name":"Gitlab Test",
- "description":"Aut reprehenderit ut est.",
- "web_url":"http://example.com/gitlabhq/gitlab-test",
- "avatar_url":null,
- "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git",
- "git_http_url":"http://example.com/gitlabhq/gitlab-test.git",
- "namespace":"GitlabHQ",
- "visibility_level":20,
- "path_with_namespace":"gitlabhq/gitlab-test",
- "default_branch":"master",
- "homepage":"http://example.com/gitlabhq/gitlab-test",
- "url":"http://example.com/gitlabhq/gitlab-test.git",
- "ssh_url":"git@example.com:gitlabhq/gitlab-test.git",
- "http_url":"http://example.com/gitlabhq/gitlab-test.git"
- },
- "repository":{
- "name": "Gitlab Test",
- "url": "http://example.com/gitlab-org/gitlab-test.git",
- "description": "Aut reprehenderit ut est.",
- "homepage": "http://example.com/gitlab-org/gitlab-test"
- },
- "object_attributes": {
- "id": 1243,
- "note": "This is a commit comment. How does this work?",
- "noteable_type": "Commit",
- "author_id": 1,
- "created_at": "2015-05-17 18:08:09 UTC",
- "updated_at": "2015-05-17 18:08:09 UTC",
- "project_id": 5,
- "attachment":null,
- "line_code": "bec9703f7a456cd2b4ab5fb3220ae016e3e394e3_0_1",
- "commit_id": "cfe32cf61b73a0d5e9f13e774abde7ff789b1660",
- "noteable_id": null,
- "system": false,
- "st_diff": {
- "diff": "--- /dev/null\n+++ b/six\n@@ -0,0 +1 @@\n+Subproject commit 409f37c4f05865e4fb208c771485f211a22c4c2d\n",
- "new_path": "six",
- "old_path": "six",
- "a_mode": "0",
- "b_mode": "160000",
- "new_file": true,
- "renamed_file": false,
- "deleted_file": false
- },
- "url": "http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660#note_1243"
- },
- "commit": {
- "id": "cfe32cf61b73a0d5e9f13e774abde7ff789b1660",
- "message": "Add submodule\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n",
- "timestamp": "2014-02-27T10:06:20+02:00",
- "url": "http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660",
- "author": {
- "name": "Dmitriy Zaporozhets",
- "email": "dmitriy.zaporozhets@gmail.com"
- }
- }
-}
-```
-
-### Comment on merge request
-
-**Request header**:
-
-```
-X-Gitlab-Event: Note Hook
-```
-
-**Request body:**
-
-```json
-{
- "object_kind": "note",
- "user": {
- "name": "Administrator",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
- },
- "project_id": 5,
- "project":{
- "name":"Gitlab Test",
- "description":"Aut reprehenderit ut est.",
- "web_url":"http://example.com/gitlab-org/gitlab-test",
- "avatar_url":null,
- "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
- "git_http_url":"http://example.com/gitlab-org/gitlab-test.git",
- "namespace":"Gitlab Org",
- "visibility_level":10,
- "path_with_namespace":"gitlab-org/gitlab-test",
- "default_branch":"master",
- "homepage":"http://example.com/gitlab-org/gitlab-test",
- "url":"http://example.com/gitlab-org/gitlab-test.git",
- "ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
- "http_url":"http://example.com/gitlab-org/gitlab-test.git"
- },
- "repository":{
- "name": "Gitlab Test",
- "url": "http://localhost/gitlab-org/gitlab-test.git",
- "description": "Aut reprehenderit ut est.",
- "homepage": "http://example.com/gitlab-org/gitlab-test"
- },
- "object_attributes": {
- "id": 1244,
- "note": "This MR needs work.",
- "noteable_type": "MergeRequest",
- "author_id": 1,
- "created_at": "2015-05-17 18:21:36 UTC",
- "updated_at": "2015-05-17 18:21:36 UTC",
- "project_id": 5,
- "attachment": null,
- "line_code": null,
- "commit_id": "",
- "noteable_id": 7,
- "system": false,
- "st_diff": null,
- "url": "http://example.com/gitlab-org/gitlab-test/merge_requests/1#note_1244"
- },
- "merge_request": {
- "id": 7,
- "target_branch": "markdown",
- "source_branch": "master",
- "source_project_id": 5,
- "author_id": 8,
- "assignee_id": 28,
- "title": "Tempora et eos debitis quae laborum et.",
- "created_at": "2015-03-01 20:12:53 UTC",
- "updated_at": "2015-03-21 18:27:27 UTC",
- "milestone_id": 11,
- "state": "opened",
- "merge_status": "cannot_be_merged",
- "target_project_id": 5,
- "iid": 1,
- "description": "Et voluptas corrupti assumenda temporibus. Architecto cum animi eveniet amet asperiores. Vitae numquam voluptate est natus sit et ad id.",
- "position": 0,
- "locked_at": null,
- "source":{
- "name":"Gitlab Test",
- "description":"Aut reprehenderit ut est.",
- "web_url":"http://example.com/gitlab-org/gitlab-test",
- "avatar_url":null,
- "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
- "git_http_url":"http://example.com/gitlab-org/gitlab-test.git",
- "namespace":"Gitlab Org",
- "visibility_level":10,
- "path_with_namespace":"gitlab-org/gitlab-test",
- "default_branch":"master",
- "homepage":"http://example.com/gitlab-org/gitlab-test",
- "url":"http://example.com/gitlab-org/gitlab-test.git",
- "ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
- "http_url":"http://example.com/gitlab-org/gitlab-test.git"
- },
- "target": {
- "name":"Gitlab Test",
- "description":"Aut reprehenderit ut est.",
- "web_url":"http://example.com/gitlab-org/gitlab-test",
- "avatar_url":null,
- "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
- "git_http_url":"http://example.com/gitlab-org/gitlab-test.git",
- "namespace":"Gitlab Org",
- "visibility_level":10,
- "path_with_namespace":"gitlab-org/gitlab-test",
- "default_branch":"master",
- "homepage":"http://example.com/gitlab-org/gitlab-test",
- "url":"http://example.com/gitlab-org/gitlab-test.git",
- "ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
- "http_url":"http://example.com/gitlab-org/gitlab-test.git"
- },
- "last_commit": {
- "id": "562e173be03b8ff2efb05345d12df18815438a4b",
- "message": "Merge branch 'another-branch' into 'master'\n\nCheck in this test\n",
- "timestamp": "2015-04-08T21: 00:25-07:00",
- "url": "http://example.com/gitlab-org/gitlab-test/commit/562e173be03b8ff2efb05345d12df18815438a4b",
- "author": {
- "name": "John Smith",
- "email": "john@example.com"
- }
- },
- "work_in_progress": false,
- "assignee": {
- "name": "User1",
- "username": "user1",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
- }
- }
-}
-```
-
-### Comment on issue
-
-**Request header**:
-
-```
-X-Gitlab-Event: Note Hook
-```
-
-**Request body:**
-
-```json
-{
- "object_kind": "note",
- "user": {
- "name": "Administrator",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
- },
- "project_id": 5,
- "project":{
- "name":"Gitlab Test",
- "description":"Aut reprehenderit ut est.",
- "web_url":"http://example.com/gitlab-org/gitlab-test",
- "avatar_url":null,
- "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
- "git_http_url":"http://example.com/gitlab-org/gitlab-test.git",
- "namespace":"Gitlab Org",
- "visibility_level":10,
- "path_with_namespace":"gitlab-org/gitlab-test",
- "default_branch":"master",
- "homepage":"http://example.com/gitlab-org/gitlab-test",
- "url":"http://example.com/gitlab-org/gitlab-test.git",
- "ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
- "http_url":"http://example.com/gitlab-org/gitlab-test.git"
- },
- "repository":{
- "name":"diaspora",
- "url":"git@example.com:mike/diaspora.git",
- "description":"",
- "homepage":"http://example.com/mike/diaspora"
- },
- "object_attributes": {
- "id": 1241,
- "note": "Hello world",
- "noteable_type": "Issue",
- "author_id": 1,
- "created_at": "2015-05-17 17:06:40 UTC",
- "updated_at": "2015-05-17 17:06:40 UTC",
- "project_id": 5,
- "attachment": null,
- "line_code": null,
- "commit_id": "",
- "noteable_id": 92,
- "system": false,
- "st_diff": null,
- "url": "http://example.com/gitlab-org/gitlab-test/issues/17#note_1241"
- },
- "issue": {
- "id": 92,
- "title": "test",
- "assignee_id": null,
- "author_id": 1,
- "project_id": 5,
- "created_at": "2015-04-12 14:53:17 UTC",
- "updated_at": "2015-04-26 08:28:42 UTC",
- "position": 0,
- "branch_name": null,
- "description": "test",
- "milestone_id": null,
- "state": "closed",
- "iid": 17
- }
-}
-```
-
-### Comment on code snippet
-
-**Request header**:
-
-```
-X-Gitlab-Event: Note Hook
-```
-
-**Request body:**
-
-```json
-{
- "object_kind": "note",
- "user": {
- "name": "Administrator",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
- },
- "project_id": 5,
- "project":{
- "name":"Gitlab Test",
- "description":"Aut reprehenderit ut est.",
- "web_url":"http://example.com/gitlab-org/gitlab-test",
- "avatar_url":null,
- "git_ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
- "git_http_url":"http://example.com/gitlab-org/gitlab-test.git",
- "namespace":"Gitlab Org",
- "visibility_level":10,
- "path_with_namespace":"gitlab-org/gitlab-test",
- "default_branch":"master",
- "homepage":"http://example.com/gitlab-org/gitlab-test",
- "url":"http://example.com/gitlab-org/gitlab-test.git",
- "ssh_url":"git@example.com:gitlab-org/gitlab-test.git",
- "http_url":"http://example.com/gitlab-org/gitlab-test.git"
- },
- "repository":{
- "name":"Gitlab Test",
- "url":"http://example.com/gitlab-org/gitlab-test.git",
- "description":"Aut reprehenderit ut est.",
- "homepage":"http://example.com/gitlab-org/gitlab-test"
- },
- "object_attributes": {
- "id": 1245,
- "note": "Is this snippet doing what it's supposed to be doing?",
- "noteable_type": "Snippet",
- "author_id": 1,
- "created_at": "2015-05-17 18:35:50 UTC",
- "updated_at": "2015-05-17 18:35:50 UTC",
- "project_id": 5,
- "attachment": null,
- "line_code": null,
- "commit_id": "",
- "noteable_id": 53,
- "system": false,
- "st_diff": null,
- "url": "http://example.com/gitlab-org/gitlab-test/snippets/53#note_1245"
- },
- "snippet": {
- "id": 53,
- "title": "test",
- "content": "puts 'Hello world'",
- "author_id": 1,
- "project_id": 5,
- "created_at": "2015-04-09 02:40:38 UTC",
- "updated_at": "2015-04-09 02:40:38 UTC",
- "file_name": "test.rb",
- "expires_at": null,
- "type": "ProjectSnippet",
- "visibility_level": 0
- }
-}
-```
-
-## Merge request events
-
-Triggered when a new merge request is created, an existing merge request was updated/merged/closed or a commit is added in the source branch.
-
-**Request header**:
-
-```
-X-Gitlab-Event: Merge Request Hook
-```
-
-**Request body:**
-
-```json
-{
- "object_kind": "merge_request",
- "user": {
- "name": "Administrator",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
- },
- "object_attributes": {
- "id": 99,
- "target_branch": "master",
- "source_branch": "ms-viewport",
- "source_project_id": 14,
- "author_id": 51,
- "assignee_id": 6,
- "title": "MS-Viewport",
- "created_at": "2013-12-03T17:23:34Z",
- "updated_at": "2013-12-03T17:23:34Z",
- "st_commits": null,
- "st_diffs": null,
- "milestone_id": null,
- "state": "opened",
- "merge_status": "unchecked",
- "target_project_id": 14,
- "iid": 1,
- "description": "",
- "source":{
- "name":"Awesome Project",
- "description":"Aut reprehenderit ut est.",
- "web_url":"http://example.com/awesome_space/awesome_project",
- "avatar_url":null,
- "git_ssh_url":"git@example.com:awesome_space/awesome_project.git",
- "git_http_url":"http://example.com/awesome_space/awesome_project.git",
- "namespace":"Awesome Space",
- "visibility_level":20,
- "path_with_namespace":"awesome_space/awesome_project",
- "default_branch":"master",
- "homepage":"http://example.com/awesome_space/awesome_project",
- "url":"http://example.com/awesome_space/awesome_project.git",
- "ssh_url":"git@example.com:awesome_space/awesome_project.git",
- "http_url":"http://example.com/awesome_space/awesome_project.git"
- },
- "target": {
- "name":"Awesome Project",
- "description":"Aut reprehenderit ut est.",
- "web_url":"http://example.com/awesome_space/awesome_project",
- "avatar_url":null,
- "git_ssh_url":"git@example.com:awesome_space/awesome_project.git",
- "git_http_url":"http://example.com/awesome_space/awesome_project.git",
- "namespace":"Awesome Space",
- "visibility_level":20,
- "path_with_namespace":"awesome_space/awesome_project",
- "default_branch":"master",
- "homepage":"http://example.com/awesome_space/awesome_project",
- "url":"http://example.com/awesome_space/awesome_project.git",
- "ssh_url":"git@example.com:awesome_space/awesome_project.git",
- "http_url":"http://example.com/awesome_space/awesome_project.git"
- },
- "last_commit": {
- "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
- "message": "fixed readme",
- "timestamp": "2012-01-03T23:36:29+02:00",
- "url": "http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
- "author": {
- "name": "GitLab dev user",
- "email": "gitlabdev@dv6700.(none)"
- }
- },
- "work_in_progress": false,
- "url": "http://example.com/diaspora/merge_requests/1",
- "action": "open",
- "assignee": {
- "name": "User1",
- "username": "user1",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
- }
- }
-}
-```
-
-## Wiki Page events
-
-Triggered when a wiki page is created or edited.
-
-**Request Header**:
-
-```
-X-Gitlab-Event: Wiki Page Hook
-```
-
-**Request Body**:
-
-```json
-{
- "object_kind": "wiki_page",
- "user": {
- "name": "Administrator",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon"
- },
- "project": {
- "name": "awesome-project",
- "description": "This is awesome",
- "web_url": "http://example.com/root/awesome-project",
- "avatar_url": null,
- "git_ssh_url": "git@example.com:root/awesome-project.git",
- "git_http_url": "http://example.com/root/awesome-project.git",
- "namespace": "root",
- "visibility_level": 0,
- "path_with_namespace": "root/awesome-project",
- "default_branch": "master",
- "homepage": "http://example.com/root/awesome-project",
- "url": "git@example.com:root/awesome-project.git",
- "ssh_url": "git@example.com:root/awesome-project.git",
- "http_url": "http://example.com/root/awesome-project.git"
- },
- "wiki": {
- "web_url": "http://example.com/root/awesome-project/wikis/home",
- "git_ssh_url": "git@example.com:root/awesome-project.wiki.git",
- "git_http_url": "http://example.com/root/awesome-project.wiki.git",
- "path_with_namespace": "root/awesome-project.wiki",
- "default_branch": "master"
- },
- "object_attributes": {
- "title": "Awesome",
- "content": "awesome content goes here",
- "format": "markdown",
- "message": "adding an awesome page to the wiki",
- "slug": "awesome",
- "url": "http://example.com/root/awesome-project/wikis/awesome",
- "action": "create"
- }
-}
-```
-
-## Pipeline events
-
-Triggered on status change of Pipeline.
-
-**Request Header**:
-
-```
-X-Gitlab-Event: Pipeline Hook
-```
-
-**Request Body**:
-
-```json
-{
- "object_kind": "pipeline",
- "object_attributes":{
- "id": 31,
- "ref": "master",
- "tag": false,
- "sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
- "before_sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
- "status": "success",
- "stages":[
- "build",
- "test",
- "deploy"
- ],
- "created_at": "2016-08-12 15:23:28 UTC",
- "finished_at": "2016-08-12 15:26:29 UTC",
- "duration": 63
- },
- "user":{
- "name": "Administrator",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
- },
- "project":{
- "name": "Gitlab Test",
- "description": "Atque in sunt eos similique dolores voluptatem.",
- "web_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test",
- "avatar_url": null,
- "git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git",
- "git_http_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test.git",
- "namespace": "Gitlab Org",
- "visibility_level": 20,
- "path_with_namespace": "gitlab-org/gitlab-test",
- "default_branch": "master"
- },
- "commit":{
- "id": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
- "message": "test\n",
- "timestamp": "2016-08-12T17:23:21+02:00",
- "url": "http://example.com/gitlab-org/gitlab-test/commit/bcbb5ec396a2c0f828686f14fac9b80b780504f2",
- "author":{
- "name": "User",
- "email": "user@gitlab.com"
- }
- },
- "builds":[
- {
- "id": 380,
- "stage": "deploy",
- "name": "production",
- "status": "skipped",
- "created_at": "2016-08-12 15:23:28 UTC",
- "started_at": null,
- "finished_at": null,
- "when": "manual",
- "manual": true,
- "user":{
- "name": "Administrator",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
- },
- "runner": null,
- "artifacts_file":{
- "filename": null,
- "size": null
- }
- },
- {
- "id": 377,
- "stage": "test",
- "name": "test-image",
- "status": "success",
- "created_at": "2016-08-12 15:23:28 UTC",
- "started_at": "2016-08-12 15:26:12 UTC",
- "finished_at": null,
- "when": "on_success",
- "manual": false,
- "user":{
- "name": "Administrator",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
- },
- "runner": null,
- "artifacts_file":{
- "filename": null,
- "size": null
- }
- },
- {
- "id": 378,
- "stage": "test",
- "name": "test-build",
- "status": "success",
- "created_at": "2016-08-12 15:23:28 UTC",
- "started_at": "2016-08-12 15:26:12 UTC",
- "finished_at": "2016-08-12 15:26:29 UTC",
- "when": "on_success",
- "manual": false,
- "user":{
- "name": "Administrator",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
- },
- "runner": null,
- "artifacts_file":{
- "filename": null,
- "size": null
- }
- },
- {
- "id": 376,
- "stage": "build",
- "name": "build-image",
- "status": "success",
- "created_at": "2016-08-12 15:23:28 UTC",
- "started_at": "2016-08-12 15:24:56 UTC",
- "finished_at": "2016-08-12 15:25:26 UTC",
- "when": "on_success",
- "manual": false,
- "user":{
- "name": "Administrator",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
- },
- "runner": null,
- "artifacts_file":{
- "filename": null,
- "size": null
- }
- },
- {
- "id": 379,
- "stage": "deploy",
- "name": "staging",
- "status": "created",
- "created_at": "2016-08-12 15:23:28 UTC",
- "started_at": null,
- "finished_at": null,
- "when": "on_success",
- "manual": false,
- "user":{
- "name": "Administrator",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
- },
- "runner": null,
- "artifacts_file":{
- "filename": null,
- "size": null
- }
- }
- ]
-}
-```
-
-#### Example webhook receiver
-
-If you want to see GitLab's webhooks in action for testing purposes you can use
-a simple echo script running in a console session.
-
-Save the following file as `print_http_body.rb`.
-
-```ruby
-require 'webrick'
-
-server = WEBrick::HTTPServer.new(:Port => ARGV.first)
-server.mount_proc '/' do |req, res|
- puts req.body
-end
-
-trap 'INT' do
- server.shutdown
-end
-server.start
-```
-
-Pick an unused port (e.g. 8000) and start the script: `ruby print_http_body.rb
-8000`. Then add your server as a webhook receiver in GitLab as
-`http://my.host:8000/`.
-
-When you press 'Test Hook' in GitLab, you should see something like this in the console.
-
-```
-{"before":"077a85dd266e6f3573ef7e9ef8ce3343ad659c4e","after":"95cd4a99e93bc4bbabacfa2cd10e6725b1403c60",<SNIP>}
-example.com - - [14/May/2014:07:45:26 EDT] "POST / HTTP/1.1" 200 0
-- -> /
-```
+This document was moved to [project/integrations/webhooks](../user/project/integrations/webhooks.md).
diff --git a/doc/workflow/README.md b/doc/workflow/README.md
index 2d9bfbc0629..54d4028a50a 100644
--- a/doc/workflow/README.md
+++ b/doc/workflow/README.md
@@ -7,6 +7,10 @@
- [Feature branch workflow](workflow.md)
- [GitLab Flow](gitlab_flow.md)
- [Groups](groups.md)
+- Issues - The GitLab Issue Tracker is an advanced and complete tool for
+ tracking the evolution of a new idea or the process of solving a problem.
+ - [Confidential issues](../user/project/issues/confidential_issues.md)
+ - [Due date for issues](../user/project/issues/due_dates.md)
- [Issue Board](../user/project/issue_board.md)
- [Keyboard shortcuts](shortcuts.md)
- [File finder](file_finder.md)
@@ -16,21 +20,25 @@
- [Project forking workflow](forking_workflow.md)
- [Project users](add-user/add-user.md)
- [Protected branches](../user/project/protected_branches.md)
-- [Slash commands](../user/project/slash_commands.md)
+- [Protected tags](../user/project/protected_tags.md)
+- [Quick Actions](../user/project/quick_actions.md)
- [Sharing a project with a group](share_with_group.md)
- [Share projects with other groups](share_projects_with_other_groups.md)
+- [Time tracking](time_tracking.md)
- [Web Editor](../user/project/repository/web_editor.md)
- [Releases](releases.md)
-- [Milestones](milestones.md)
-- [Merge Requests](../user/project/merge_requests.md)
+- [Milestones](../user/project/milestones/index.md)
+- [Merge Requests](../user/project/merge_requests/index.md)
- [Authorization for merge requests](../user/project/merge_requests/authorization_for_merge_requests.md)
- [Cherry-pick changes](../user/project/merge_requests/cherry_pick_changes.md)
- - [Merge when build succeeds](../user/project/merge_requests/merge_when_build_succeeds.md)
- - [Resolve discussion comments in merge requests reviews](../user/project/merge_requests/merge_request_discussion_resolution.md)
+ - [Merge when pipeline succeeds](../user/project/merge_requests/merge_when_pipeline_succeeds.md)
+ - [Resolve discussion comments in merge requests reviews](../user/discussions/index.md)
- [Resolve merge conflicts in the UI](../user/project/merge_requests/resolve_conflicts.md)
- [Revert changes in the UI](../user/project/merge_requests/revert_changes.md)
- [Merge requests versions](../user/project/merge_requests/versions.md)
- ["Work In Progress" merge requests](../user/project/merge_requests/work_in_progress_merge_requests.md)
- [Manage large binaries with Git LFS](lfs/manage_large_binaries_with_git_lfs.md)
-- [Importing from SVN, GitHub, BitBucket, etc](importing/README.md)
+- [Importing from SVN, GitHub, Bitbucket, etc](importing/README.md)
- [Todos](todos.md)
+- [Snippets](../user/snippets.md)
+- [Subgroups](../user/group/subgroups/index.md)
diff --git a/doc/workflow/add-user/img/access_requests_management.png b/doc/workflow/add-user/img/access_requests_management.png
index 5c9b510ba9d..3693bed869b 100644
--- a/doc/workflow/add-user/img/access_requests_management.png
+++ b/doc/workflow/add-user/img/access_requests_management.png
Binary files differ
diff --git a/doc/workflow/add-user/img/add_new_user_to_project_settings.png b/doc/workflow/add-user/img/add_new_user_to_project_settings.png
index 5da0552f9d6..40db600455f 100644
--- a/doc/workflow/add-user/img/add_new_user_to_project_settings.png
+++ b/doc/workflow/add-user/img/add_new_user_to_project_settings.png
Binary files differ
diff --git a/doc/workflow/add-user/img/add_user_email_accept.png b/doc/workflow/add-user/img/add_user_email_accept.png
index a2954ad7c37..763b3ff463d 100644
--- a/doc/workflow/add-user/img/add_user_email_accept.png
+++ b/doc/workflow/add-user/img/add_user_email_accept.png
Binary files differ
diff --git a/doc/workflow/add-user/img/add_user_email_ready.png b/doc/workflow/add-user/img/add_user_email_ready.png
index 19d91bc0999..0066eb3427b 100644
--- a/doc/workflow/add-user/img/add_user_email_ready.png
+++ b/doc/workflow/add-user/img/add_user_email_ready.png
Binary files differ
diff --git a/doc/workflow/add-user/img/add_user_email_search.png b/doc/workflow/add-user/img/add_user_email_search.png
index cb31b77d941..66bcd6aad80 100644
--- a/doc/workflow/add-user/img/add_user_email_search.png
+++ b/doc/workflow/add-user/img/add_user_email_search.png
Binary files differ
diff --git a/doc/workflow/add-user/img/add_user_give_permissions.png b/doc/workflow/add-user/img/add_user_give_permissions.png
index e6b77022f06..376a3eefccc 100644
--- a/doc/workflow/add-user/img/add_user_give_permissions.png
+++ b/doc/workflow/add-user/img/add_user_give_permissions.png
Binary files differ
diff --git a/doc/workflow/add-user/img/add_user_import_members_from_another_project.png b/doc/workflow/add-user/img/add_user_import_members_from_another_project.png
index 1068589c5ff..0c32001098e 100644
--- a/doc/workflow/add-user/img/add_user_import_members_from_another_project.png
+++ b/doc/workflow/add-user/img/add_user_import_members_from_another_project.png
Binary files differ
diff --git a/doc/workflow/add-user/img/add_user_imported_members.png b/doc/workflow/add-user/img/add_user_imported_members.png
index 5cd120a4245..51fd7688890 100644
--- a/doc/workflow/add-user/img/add_user_imported_members.png
+++ b/doc/workflow/add-user/img/add_user_imported_members.png
Binary files differ
diff --git a/doc/workflow/add-user/img/add_user_list_members.png b/doc/workflow/add-user/img/add_user_list_members.png
index 5fe3482192e..e0fa404288d 100644
--- a/doc/workflow/add-user/img/add_user_list_members.png
+++ b/doc/workflow/add-user/img/add_user_list_members.png
Binary files differ
diff --git a/doc/workflow/add-user/img/add_user_members_menu.png b/doc/workflow/add-user/img/add_user_members_menu.png
index 340d15c9830..8e61d15fe65 100644
--- a/doc/workflow/add-user/img/add_user_members_menu.png
+++ b/doc/workflow/add-user/img/add_user_members_menu.png
Binary files differ
diff --git a/doc/workflow/add-user/img/add_user_search_people.png b/doc/workflow/add-user/img/add_user_search_people.png
index 1c05d70ca31..41767a9167c 100644
--- a/doc/workflow/add-user/img/add_user_search_people.png
+++ b/doc/workflow/add-user/img/add_user_search_people.png
Binary files differ
diff --git a/doc/workflow/add-user/img/request_access_button.png b/doc/workflow/add-user/img/request_access_button.png
index 984d640b0f0..608baccb0ca 100644
--- a/doc/workflow/add-user/img/request_access_button.png
+++ b/doc/workflow/add-user/img/request_access_button.png
Binary files differ
diff --git a/doc/workflow/add-user/img/withdraw_access_request_button.png b/doc/workflow/add-user/img/withdraw_access_request_button.png
index ff54a0e4384..6edd786b151 100644
--- a/doc/workflow/add-user/img/withdraw_access_request_button.png
+++ b/doc/workflow/add-user/img/withdraw_access_request_button.png
Binary files differ
diff --git a/doc/workflow/award_emoji.md b/doc/workflow/award_emoji.md
index 1df0698afd0..d74378cc564 100644
--- a/doc/workflow/award_emoji.md
+++ b/doc/workflow/award_emoji.md
@@ -1,65 +1 @@
-# Award emoji
-
->**Note:**
-[Introduced][1825] in GitLab 8.2.
-
-When you're collaborating online, you get fewer opportunities for high-fives
-and thumbs-ups. Emoji can be awarded to issues and merge requests, making
-virtual celebrations easier.
-
-![Award emoji](img/award_emoji_select.png)
-
-Award emoji make it much easier to give and receive feedback without a long
-comment thread. Comments that are only emoji will automatically become
-award emoji.
-
-## Sort issues and merge requests on vote count
-
->**Note:**
-[Introduced][2871] in GitLab 8.5.
-
-You can quickly sort issues and merge requests by the number of votes they
-have received. The sort options can be found in the dropdown menu as "Most
-popular" and "Least popular".
-
-![Votes sort options](img/award_emoji_votes_sort_options.png)
-
----
-
-Sort by most popular issues/merge requests.
-
-![Votes sort by most popular](img/award_emoji_votes_most_popular.png)
-
----
-
-Sort by least popular issues/merge requests.
-
-![Votes sort by least popular](img/award_emoji_votes_least_popular.png)
-
----
-
-The total number of votes is not summed up. An issue with 18 upvotes and 5
-downvotes is considered more popular than an issue with 17 upvotes and no
-downvotes.
-
-## Award emoji for comments
-
->**Note:**
-[Introduced][4291] in GitLab 8.9.
-
-Award emoji can also be applied to individual comments when you want to
-celebrate an accomplishment or agree with an opinion.
-
-To add an award emoji, click the smile in the top right of the comment and pick
-an emoji from the dropdown.
-
-![Picking an emoji for a comment](img/award_emoji_comment_picker.png)
-
-![An award emoji has been applied to a comment](img/award_emoji_comment_awarded.png)
-
-If you want to remove an award emoji, just click the emoji again and the vote
-will be removed.
-
-[2871]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2781
-[1825]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/1825
-[4291]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4291
+This document was moved to [another location](../user/award_emojis.md).
diff --git a/doc/workflow/award_emoji.png b/doc/workflow/award_emoji.png
index 481680af80c..1ad634a343e 100644
--- a/doc/workflow/award_emoji.png
+++ b/doc/workflow/award_emoji.png
Binary files differ
diff --git a/doc/workflow/ci_mr.png b/doc/workflow/ci_mr.png
index f8a7708643e..77423c68190 100644
--- a/doc/workflow/ci_mr.png
+++ b/doc/workflow/ci_mr.png
Binary files differ
diff --git a/doc/workflow/close_issue_mr.png b/doc/workflow/close_issue_mr.png
index 5e520240233..70de2fb6cee 100644
--- a/doc/workflow/close_issue_mr.png
+++ b/doc/workflow/close_issue_mr.png
Binary files differ
diff --git a/doc/workflow/environment_branches.png b/doc/workflow/environment_branches.png
index 13fb0478eaa..0941a4cad9c 100644
--- a/doc/workflow/environment_branches.png
+++ b/doc/workflow/environment_branches.png
Binary files differ
diff --git a/doc/workflow/forking/branch_select.png b/doc/workflow/forking/branch_select.png
index 7f19414f3a9..3e82afca75b 100644
--- a/doc/workflow/forking/branch_select.png
+++ b/doc/workflow/forking/branch_select.png
Binary files differ
diff --git a/doc/workflow/forking/merge_request.png b/doc/workflow/forking/merge_request.png
index e2da42a2be7..294775e1fdd 100644
--- a/doc/workflow/forking/merge_request.png
+++ b/doc/workflow/forking/merge_request.png
Binary files differ
diff --git a/doc/workflow/four_stages.png b/doc/workflow/four_stages.png
index 49413087dca..3ef6a33d2d4 100644
--- a/doc/workflow/four_stages.png
+++ b/doc/workflow/four_stages.png
Binary files differ
diff --git a/doc/workflow/git_pull.png b/doc/workflow/git_pull.png
index 9a1fdf899bf..2dd06b56c56 100644
--- a/doc/workflow/git_pull.png
+++ b/doc/workflow/git_pull.png
Binary files differ
diff --git a/doc/workflow/gitdashflow.png b/doc/workflow/gitdashflow.png
index e456cf9309d..65900853d84 100644
--- a/doc/workflow/gitdashflow.png
+++ b/doc/workflow/gitdashflow.png
Binary files differ
diff --git a/doc/workflow/github_flow.png b/doc/workflow/github_flow.png
index b3fca97cc2d..21a22becdb6 100644
--- a/doc/workflow/github_flow.png
+++ b/doc/workflow/github_flow.png
Binary files differ
diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md
index 7c0eb90d540..e10ccc4fc46 100644
--- a/doc/workflow/gitlab_flow.md
+++ b/doc/workflow/gitlab_flow.md
@@ -67,7 +67,7 @@ With GitLab flow we offer additional guidance for these questions.
![Master branch and production branch with arrow that indicate deployments](production_branch.png)
GitHub flow does assume you are able to deploy to production every time you merge a feature branch.
-This is possible for SaaS applications but are many cases where this is not possible.
+This is possible for e.g. SaaS applications, but there are many cases where this is not possible.
One would be a situation where you are not in control of the exact release moment, for example an iOS application that needs to pass App Store validation.
Another example is when you have deployment windows (workdays from 10am to 4pm when the operations team is at full capacity) but you also merge code at other times.
In these cases you can make a production branch that reflects the deployed code.
@@ -134,7 +134,7 @@ If the assigned person does not feel comfortable they can close the merge reques
In GitLab it is common to protect the long-lived branches (e.g. the master branch) so that normal developers [can't modify these protected branches](http://docs.gitlab.com/ce/permissions/permissions.html).
So if you want to merge it into a protected branch you assign it to someone with master authorizations.
-## Issues with GitLab flow
+## Issue tracking with GitLab flow
![Merge request with the branch name 15-require-a-password-to-change-it and assignee field shown](merge_request.png)
@@ -173,9 +173,9 @@ It is possible that one feature branch solves more than one issue.
![Merge request showing the linked issues that will be closed](close_issue_mr.png)
-Linking to the issue can happen by mentioning them from commit messages (fixes #14, closes #67, etc.) or from the merge request description.
-In GitLab this creates a comment in the issue that the merge requests mentions the issue.
-And the merge request shows the linked issues.
+Linking to issues can happen by mentioning them in commit messages (fixes #14, closes #67, etc.) or in the merge request description.
+GitLab then creates links to the mentioned issues and creates comments in the corresponding issues linking back to the merge request.
+
These issues are closed once code is merged into the default branch.
If you only want to make the reference without closing the issue you can also just mention it: "Duck typing is preferred. #12".
@@ -203,7 +203,7 @@ But the advantages of having stable identifiers outweigh this drawback.
And to understand a change in context one can always look at the merge commit that groups all the commits together when the code is merged into the master branch.
After you merge multiple commits from a feature branch into the master branch this is harder to undo.
-If you would have squashed all the commits into one you could have just reverted this commit but as we indicated you should not rebase commits after they are pushed.
+If you had squashed all the commits into one you could have just reverted this commit but as we indicated you should not rebase commits after they are pushed.
Fortunately [reverting a merge made some time ago](https://git-scm.com/blog/2010/03/02/undoing-merges.html) can be done with git.
This however, requires having specific merge commits for the commits your want to revert.
If you revert a merge and you change your mind, revert the revert instead of merging again since git will not allow you to merge the code again otherwise.
@@ -228,7 +228,7 @@ We'll discuss the three reasons to merge in master: leveraging code, merge confl
If you need to leverage some code that was introduced in master after you created the feature branch you can sometimes solve this by just cherry-picking a commit.
If your feature branch has a merge conflict, creating a merge commit is a normal way of solving this.
You can prevent some merge conflicts by using [gitattributes](http://git-scm.com/docs/gitattributes) for files that can be in a random order.
-For example in GitLab our changelog file is specified in .gitattributes as `CHANGELOG merge=union` so that there are fewer merge conflicts in it.
+For example in GitLab our changelog file is specified in .gitattributes as `CHANGELOG.md merge=union` so that there are fewer merge conflicts in it.
The last reason for creating merge commits is having long lived branches that you want to keep up to date with the latest state of the project.
Martin Fowler, in [his article about feature branches](http://martinfowler.com/bliki/FeatureBranch.html) talks about this Continuous Integration (CI).
At GitLab we are guilty of confusing CI with branch testing. Quoting Martin Fowler: "I've heard people say they are doing CI because they are running builds, perhaps using a CI server, on every branch with every commit.
@@ -279,7 +279,7 @@ The trick is to use the merge/pull request with multiple commits when your work
The commit message should reflect your intention, not the contents of the commit.
The contents of the commit can be easily seen anyway, the question is why you did it.
An example of a good commit message is: "Combine templates to dry up the user views.".
-Some words that are bad commit messages because they don't contain munch information are: change, improve and refactor.
+Some words that are bad commit messages because they don't contain much information are: change, improve and refactor.
The word fix or fixes is also a red flag, unless it comes after the commit sentence and references an issue number.
To see more information about the formatting of commit messages please see this great [blog post by Tim Pope](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
@@ -300,7 +300,7 @@ If there are no merge conflicts and the feature branches are short lived the ris
If there are merge conflicts you merge the master branch into the feature branch and the CI server will rerun the tests.
If you have long lived feature branches that last for more than a few days you should make your issues smaller.
-## Merging in other code
+## Working wih feature branches
![Shell output showing git pull output](git_pull.png)
@@ -313,5 +313,4 @@ Merging only when needed prevents creating merge commits in your feature branch
### References
-- [Sketch file](https://www.dropbox.com/s/58dvsj5votbwrzv/git_flows.sketch?dl=0) with vectors of images in this article
- [Git Flow by Vincent Driessen](http://nvie.com/posts/a-successful-git-branching-model/)
diff --git a/doc/workflow/gitlab_flow.png b/doc/workflow/gitlab_flow.png
index d85d4ff374e..c3562cc69a8 100644
--- a/doc/workflow/gitlab_flow.png
+++ b/doc/workflow/gitlab_flow.png
Binary files differ
diff --git a/doc/workflow/good_commit.png b/doc/workflow/good_commit.png
index 7958feea4d9..c3664aa97f2 100644
--- a/doc/workflow/good_commit.png
+++ b/doc/workflow/good_commit.png
Binary files differ
diff --git a/doc/workflow/groups.md b/doc/workflow/groups.md
index a693cc3d0fd..1645e7e8d65 100644
--- a/doc/workflow/groups.md
+++ b/doc/workflow/groups.md
@@ -1,6 +1,6 @@
# GitLab Groups
-GitLab groups allow you to group projects into directories and give users to several projects at once.
+GitLab groups allow you to group projects into directories and give users access to several projects at once.
When you create a new project in GitLab, the default namespace for the project is the personal namespace associated with your GitLab user.
In this document we will see how to create groups, put projects in groups and manage who can access the projects in a group.
@@ -11,9 +11,9 @@ You can create a group by going to the 'Groups' tab of the GitLab dashboard and
![Click the 'New group' button in the 'Groups' tab](groups/new_group_button.png)
-Next, enter the name (required) and the optional description and group avatar.
+Next, enter the path and name (required) and the optional description and group avatar.
-![Fill in the name for your new group](groups/new_group_form.png)
+![Fill in the path for your new group](groups/new_group_form.png)
When your group has been created you are presented with the group dashboard feed, which will be empty.
@@ -23,9 +23,10 @@ You can use the 'New project' button to add a project to the new group.
## Transferring an existing project into a group
-You can transfer an existing project into a group you own from the project settings page.
+You can transfer an existing project into a group you have at least Master access in from the project settings page.
+The option to transfer a project is only available if you are the Owner of the project.
First scroll down to the 'Dangerous settings' and click 'Show them to me'.
-Now you can pick any of the groups you manage as the new namespace for the group.
+Now you can pick any of the groups you have at least Master access in as the new namespace for the group.
![Transfer a project to a new namespace](groups/transfer_project.png)
diff --git a/doc/workflow/groups/access_requests_management.png b/doc/workflow/groups/access_requests_management.png
index 5202434f00f..36deaa89a70 100644
--- a/doc/workflow/groups/access_requests_management.png
+++ b/doc/workflow/groups/access_requests_management.png
Binary files differ
diff --git a/doc/workflow/groups/add_member_to_group.png b/doc/workflow/groups/add_member_to_group.png
index 6e3f660d2e4..a10d5032bb0 100644
--- a/doc/workflow/groups/add_member_to_group.png
+++ b/doc/workflow/groups/add_member_to_group.png
Binary files differ
diff --git a/doc/workflow/groups/group_dashboard.png b/doc/workflow/groups/group_dashboard.png
index 662c932e536..a5829f25808 100644
--- a/doc/workflow/groups/group_dashboard.png
+++ b/doc/workflow/groups/group_dashboard.png
Binary files differ
diff --git a/doc/workflow/groups/group_with_two_projects.png b/doc/workflow/groups/group_with_two_projects.png
index dc3475949f5..76d0a1b8ab2 100644
--- a/doc/workflow/groups/group_with_two_projects.png
+++ b/doc/workflow/groups/group_with_two_projects.png
Binary files differ
diff --git a/doc/workflow/groups/max_access_level.png b/doc/workflow/groups/max_access_level.png
index 2855a514013..63f33f9d91d 100644
--- a/doc/workflow/groups/max_access_level.png
+++ b/doc/workflow/groups/max_access_level.png
Binary files differ
diff --git a/doc/workflow/groups/new_group_button.png b/doc/workflow/groups/new_group_button.png
index 26136312c8f..7155d6280bd 100644
--- a/doc/workflow/groups/new_group_button.png
+++ b/doc/workflow/groups/new_group_button.png
Binary files differ
diff --git a/doc/workflow/groups/new_group_form.png b/doc/workflow/groups/new_group_form.png
index dc50a069ef2..91727ab5336 100644
--- a/doc/workflow/groups/new_group_form.png
+++ b/doc/workflow/groups/new_group_form.png
Binary files differ
diff --git a/doc/workflow/groups/other_group_sees_shared_project.png b/doc/workflow/groups/other_group_sees_shared_project.png
index 2230720cecd..67af27043eb 100644
--- a/doc/workflow/groups/other_group_sees_shared_project.png
+++ b/doc/workflow/groups/other_group_sees_shared_project.png
Binary files differ
diff --git a/doc/workflow/groups/override_access_level.png b/doc/workflow/groups/override_access_level.png
index 9d6aaf4c363..2b3e9a49842 100644
--- a/doc/workflow/groups/override_access_level.png
+++ b/doc/workflow/groups/override_access_level.png
Binary files differ
diff --git a/doc/workflow/groups/project_members_via_group.png b/doc/workflow/groups/project_members_via_group.png
index 58270936a0b..878c9a03ac9 100644
--- a/doc/workflow/groups/project_members_via_group.png
+++ b/doc/workflow/groups/project_members_via_group.png
Binary files differ
diff --git a/doc/workflow/groups/request_access_button.png b/doc/workflow/groups/request_access_button.png
index 0eec5cb937d..f1aae6afed7 100644
--- a/doc/workflow/groups/request_access_button.png
+++ b/doc/workflow/groups/request_access_button.png
Binary files differ
diff --git a/doc/workflow/groups/share_project_with_groups.png b/doc/workflow/groups/share_project_with_groups.png
index 5772d4deced..3cb4796f9f7 100644
--- a/doc/workflow/groups/share_project_with_groups.png
+++ b/doc/workflow/groups/share_project_with_groups.png
Binary files differ
diff --git a/doc/workflow/groups/transfer_project.png b/doc/workflow/groups/transfer_project.png
index 0aef3ab3f0f..52161817f11 100644
--- a/doc/workflow/groups/transfer_project.png
+++ b/doc/workflow/groups/transfer_project.png
Binary files differ
diff --git a/doc/workflow/groups/withdraw_access_request_button.png b/doc/workflow/groups/withdraw_access_request_button.png
index b7de830a780..c5d8ef6c04f 100644
--- a/doc/workflow/groups/withdraw_access_request_button.png
+++ b/doc/workflow/groups/withdraw_access_request_button.png
Binary files differ
diff --git a/doc/workflow/img/award_emoji_comment_awarded.png b/doc/workflow/img/award_emoji_comment_awarded.png
deleted file mode 100644
index 67697831869..00000000000
--- a/doc/workflow/img/award_emoji_comment_awarded.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/img/award_emoji_comment_picker.png b/doc/workflow/img/award_emoji_comment_picker.png
deleted file mode 100644
index d9c3faecdca..00000000000
--- a/doc/workflow/img/award_emoji_comment_picker.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/img/award_emoji_select.png b/doc/workflow/img/award_emoji_select.png
deleted file mode 100644
index ad664c0aeff..00000000000
--- a/doc/workflow/img/award_emoji_select.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/img/award_emoji_votes_least_popular.png b/doc/workflow/img/award_emoji_votes_least_popular.png
deleted file mode 100644
index 57d595d9602..00000000000
--- a/doc/workflow/img/award_emoji_votes_least_popular.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/img/award_emoji_votes_most_popular.png b/doc/workflow/img/award_emoji_votes_most_popular.png
deleted file mode 100644
index 432bd09b8a7..00000000000
--- a/doc/workflow/img/award_emoji_votes_most_popular.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/img/award_emoji_votes_sort_options.png b/doc/workflow/img/award_emoji_votes_sort_options.png
deleted file mode 100644
index ae6e224b317..00000000000
--- a/doc/workflow/img/award_emoji_votes_sort_options.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/img/file_finder_find_button.png b/doc/workflow/img/file_finder_find_button.png
index 96e383f0213..23139cc00c5 100644
--- a/doc/workflow/img/file_finder_find_button.png
+++ b/doc/workflow/img/file_finder_find_button.png
Binary files differ
diff --git a/doc/workflow/img/file_finder_find_file.png b/doc/workflow/img/file_finder_find_file.png
index c6508514c76..c2212c7cd9e 100644
--- a/doc/workflow/img/file_finder_find_file.png
+++ b/doc/workflow/img/file_finder_find_file.png
Binary files differ
diff --git a/doc/workflow/img/forking_workflow_choose_namespace.png b/doc/workflow/img/forking_workflow_choose_namespace.png
index 1839d5e8be2..b34b12090a1 100644
--- a/doc/workflow/img/forking_workflow_choose_namespace.png
+++ b/doc/workflow/img/forking_workflow_choose_namespace.png
Binary files differ
diff --git a/doc/workflow/img/forking_workflow_fork_button.png b/doc/workflow/img/forking_workflow_fork_button.png
index cc79d6fd40c..29854e6c516 100644
--- a/doc/workflow/img/forking_workflow_fork_button.png
+++ b/doc/workflow/img/forking_workflow_fork_button.png
Binary files differ
diff --git a/doc/workflow/img/forking_workflow_path_taken_error.png b/doc/workflow/img/forking_workflow_path_taken_error.png
index a859155aef0..9365fd13200 100644
--- a/doc/workflow/img/forking_workflow_path_taken_error.png
+++ b/doc/workflow/img/forking_workflow_path_taken_error.png
Binary files differ
diff --git a/doc/workflow/img/new_branch_from_issue.png b/doc/workflow/img/new_branch_from_issue.png
index 61acdd30ae9..286d775bb9e 100644
--- a/doc/workflow/img/new_branch_from_issue.png
+++ b/doc/workflow/img/new_branch_from_issue.png
Binary files differ
diff --git a/doc/workflow/img/notification_global_settings.png b/doc/workflow/img/notification_global_settings.png
new file mode 100644
index 00000000000..8a5494d16a8
--- /dev/null
+++ b/doc/workflow/img/notification_global_settings.png
Binary files differ
diff --git a/doc/workflow/img/notification_group_settings.png b/doc/workflow/img/notification_group_settings.png
new file mode 100644
index 00000000000..fc096f46901
--- /dev/null
+++ b/doc/workflow/img/notification_group_settings.png
Binary files differ
diff --git a/doc/workflow/img/notification_project_settings.png b/doc/workflow/img/notification_project_settings.png
new file mode 100644
index 00000000000..006432f65c9
--- /dev/null
+++ b/doc/workflow/img/notification_project_settings.png
Binary files differ
diff --git a/doc/workflow/img/todo_list_item.png b/doc/workflow/img/todo_list_item.png
index 884ba1d22a3..076069b651e 100644
--- a/doc/workflow/img/todo_list_item.png
+++ b/doc/workflow/img/todo_list_item.png
Binary files differ
diff --git a/doc/workflow/img/todos_add_todo_sidebar.png b/doc/workflow/img/todos_add_todo_sidebar.png
index 126ecc2c82f..3fa37067d1e 100644
--- a/doc/workflow/img/todos_add_todo_sidebar.png
+++ b/doc/workflow/img/todos_add_todo_sidebar.png
Binary files differ
diff --git a/doc/workflow/img/todos_icon.png b/doc/workflow/img/todos_icon.png
index bba77f88913..9fee4337a75 100644
--- a/doc/workflow/img/todos_icon.png
+++ b/doc/workflow/img/todos_icon.png
Binary files differ
diff --git a/doc/workflow/img/todos_index.png b/doc/workflow/img/todos_index.png
index f1438ef7355..99c1575d157 100644
--- a/doc/workflow/img/todos_index.png
+++ b/doc/workflow/img/todos_index.png
Binary files differ
diff --git a/doc/workflow/img/todos_mark_done_sidebar.png b/doc/workflow/img/todos_mark_done_sidebar.png
index f449f977dd6..a8e756a71db 100644
--- a/doc/workflow/img/todos_mark_done_sidebar.png
+++ b/doc/workflow/img/todos_mark_done_sidebar.png
Binary files differ
diff --git a/doc/workflow/importing/README.md b/doc/workflow/importing/README.md
index 18e5d950866..2d91bee0e94 100644
--- a/doc/workflow/importing/README.md
+++ b/doc/workflow/importing/README.md
@@ -4,6 +4,7 @@
1. [GitHub](import_projects_from_github.md)
1. [GitLab.com](import_projects_from_gitlab_com.md)
1. [FogBugz](import_projects_from_fogbugz.md)
+1. [Gitea](import_projects_from_gitea.md)
1. [SVN](migrating_from_svn.md)
In addition to the specific migration documentation above, you can import any
@@ -14,4 +15,3 @@ repository is too large the import can timeout.
You can copy your repos by changing the remote and pushing to the new server;
but issues and merge requests can't be imported.
-
diff --git a/doc/workflow/importing/bitbucket_importer/bitbucket_import_grant_access.png b/doc/workflow/importing/bitbucket_importer/bitbucket_import_grant_access.png
deleted file mode 100644
index df55a081803..00000000000
--- a/doc/workflow/importing/bitbucket_importer/bitbucket_import_grant_access.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/importing/bitbucket_importer/bitbucket_import_new_project.png b/doc/workflow/importing/bitbucket_importer/bitbucket_import_new_project.png
deleted file mode 100644
index 5253889d251..00000000000
--- a/doc/workflow/importing/bitbucket_importer/bitbucket_import_new_project.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/importing/bitbucket_importer/bitbucket_import_select_bitbucket.png b/doc/workflow/importing/bitbucket_importer/bitbucket_import_select_bitbucket.png
deleted file mode 100644
index ffa87ce5b2e..00000000000
--- a/doc/workflow/importing/bitbucket_importer/bitbucket_import_select_bitbucket.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/importing/bitbucket_importer/bitbucket_import_select_project.png b/doc/workflow/importing/bitbucket_importer/bitbucket_import_select_project.png
deleted file mode 100644
index 1a5661de75d..00000000000
--- a/doc/workflow/importing/bitbucket_importer/bitbucket_import_select_project.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_finished.png b/doc/workflow/importing/fogbugz_importer/fogbugz_import_finished.png
index fd7a4d3fabf..62c5c86c9b3 100644
--- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_finished.png
+++ b/doc/workflow/importing/fogbugz_importer/fogbugz_import_finished.png
Binary files differ
diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_login.png b/doc/workflow/importing/fogbugz_importer/fogbugz_import_login.png
index fd1ba6f5884..96bce70b74d 100644
--- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_login.png
+++ b/doc/workflow/importing/fogbugz_importer/fogbugz_import_login.png
Binary files differ
diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_fogbogz.png b/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_fogbogz.png
index 186c1563951..b26c652e382 100644
--- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_fogbogz.png
+++ b/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_fogbogz.png
Binary files differ
diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_project.png b/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_project.png
index 2f84d3232f2..ccc82f9d4cd 100644
--- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_project.png
+++ b/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_project.png
Binary files differ
diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_user_map.png b/doc/workflow/importing/fogbugz_importer/fogbugz_import_user_map.png
index 652ca20b9ab..28ff55a8d89 100644
--- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_user_map.png
+++ b/doc/workflow/importing/fogbugz_importer/fogbugz_import_user_map.png
Binary files differ
diff --git a/doc/workflow/importing/gitlab_importer/importer.png b/doc/workflow/importing/gitlab_importer/importer.png
index 35a7ddc8318..27d42eb492e 100644
--- a/doc/workflow/importing/gitlab_importer/importer.png
+++ b/doc/workflow/importing/gitlab_importer/importer.png
Binary files differ
diff --git a/doc/workflow/importing/gitlab_importer/new_project_page.png b/doc/workflow/importing/gitlab_importer/new_project_page.png
index 81074d2d016..c673724f436 100644
--- a/doc/workflow/importing/gitlab_importer/new_project_page.png
+++ b/doc/workflow/importing/gitlab_importer/new_project_page.png
Binary files differ
diff --git a/doc/workflow/importing/img/bitbucket_import_grant_access.png b/doc/workflow/importing/img/bitbucket_import_grant_access.png
new file mode 100644
index 00000000000..429904e621d
--- /dev/null
+++ b/doc/workflow/importing/img/bitbucket_import_grant_access.png
Binary files differ
diff --git a/doc/workflow/importing/img/bitbucket_import_new_project.png b/doc/workflow/importing/img/bitbucket_import_new_project.png
new file mode 100644
index 00000000000..8ed528c2f09
--- /dev/null
+++ b/doc/workflow/importing/img/bitbucket_import_new_project.png
Binary files differ
diff --git a/doc/workflow/importing/img/bitbucket_import_select_project.png b/doc/workflow/importing/img/bitbucket_import_select_project.png
new file mode 100644
index 00000000000..1bca6166ec8
--- /dev/null
+++ b/doc/workflow/importing/img/bitbucket_import_select_project.png
Binary files differ
diff --git a/doc/workflow/importing/img/import_projects_from_gitea_new_import.png b/doc/workflow/importing/img/import_projects_from_gitea_new_import.png
new file mode 100644
index 00000000000..a3f603cbd0a
--- /dev/null
+++ b/doc/workflow/importing/img/import_projects_from_gitea_new_import.png
Binary files differ
diff --git a/doc/workflow/importing/img/import_projects_from_github_importer.png b/doc/workflow/importing/img/import_projects_from_github_importer.png
index eadd33c695f..d8effaf6075 100644
--- a/doc/workflow/importing/img/import_projects_from_github_importer.png
+++ b/doc/workflow/importing/img/import_projects_from_github_importer.png
Binary files differ
diff --git a/doc/workflow/importing/img/import_projects_from_github_new_project_page.png b/doc/workflow/importing/img/import_projects_from_github_new_project_page.png
deleted file mode 100644
index 6e91c430a33..00000000000
--- a/doc/workflow/importing/img/import_projects_from_github_new_project_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/importing/img/import_projects_from_github_select_auth_method.png b/doc/workflow/importing/img/import_projects_from_github_select_auth_method.png
index c11863ab10c..1ccb38a815e 100644
--- a/doc/workflow/importing/img/import_projects_from_github_select_auth_method.png
+++ b/doc/workflow/importing/img/import_projects_from_github_select_auth_method.png
Binary files differ
diff --git a/doc/workflow/importing/img/import_projects_from_new_project_page.png b/doc/workflow/importing/img/import_projects_from_new_project_page.png
new file mode 100644
index 00000000000..97ca30b2087
--- /dev/null
+++ b/doc/workflow/importing/img/import_projects_from_new_project_page.png
Binary files differ
diff --git a/doc/workflow/importing/import_projects_from_bitbucket.md b/doc/workflow/importing/import_projects_from_bitbucket.md
index 520c4216295..f3c636ed1d5 100644
--- a/doc/workflow/importing/import_projects_from_bitbucket.md
+++ b/doc/workflow/importing/import_projects_from_bitbucket.md
@@ -1,26 +1,62 @@
# Import your project from Bitbucket to GitLab
-It takes just a few steps to import your existing Bitbucket projects to GitLab. But keep in mind that it is possible only if Bitbucket support is enabled on your GitLab instance. You can read more about Bitbucket support [here](../../integration/bitbucket.md).
+Import your projects from Bitbucket to GitLab with minimal effort.
-* Sign in to GitLab.com and go to your dashboard
+## Overview
-* Click on "New project"
+>**Note:**
+The [Bitbucket integration][bb-import] must be first enabled in order to be
+able to import your projects from Bitbucket. Ask your GitLab administrator
+to enable this if not already.
-![New project in GitLab](bitbucket_importer/bitbucket_import_new_project.png)
+- At its current state, the Bitbucket importer can import:
+ - the repository description (GitLab 7.7+)
+ - the Git repository data (GitLab 7.7+)
+ - the issues (GitLab 7.7+)
+ - the issue comments (GitLab 8.15+)
+ - the pull requests (GitLab 8.4+)
+ - the pull request comments (GitLab 8.15+)
+ - the milestones (GitLab 8.15+)
+ - the wiki (GitLab 8.15+)
+- References to pull requests and issues are preserved (GitLab 8.7+)
+- Repository public access is retained. If a repository is private in Bitbucket
+ it will be created as private in GitLab as well.
-* Click on the "Bitbucket" button
-![Bitbucket](bitbucket_importer/bitbucket_import_select_bitbucket.png)
+## How it works
-* Grant GitLab access to your Bitbucket account
+When issues/pull requests are being imported, the Bitbucket importer tries to find
+the Bitbucket author/assignee in GitLab's database using the Bitbucket ID. For this
+to work, the Bitbucket author/assignee should have signed in beforehand in GitLab
+and **associated their Bitbucket account**. If the user is not
+found in GitLab's database, the project creator (most of the times the current
+user that started the import process) is set as the author, but a reference on
+the issue about the original Bitbucket author is kept.
-![Grant access](bitbucket_importer/bitbucket_import_grant_access.png)
+The importer will create any new namespaces (groups) if they don't exist or in
+the case the namespace is taken, the repository will be imported under the user's
+namespace that started the import process.
-* Click on the projects that you'd like to import or "Import all projects"
+## Importing your Bitbucket repositories
-![Import projects](bitbucket_importer/bitbucket_import_select_project.png)
+1. Sign in to GitLab and go to your dashboard.
+1. Click on **New project**.
-A new GitLab project will be created with your imported data.
+ ![New project in GitLab](img/bitbucket_import_new_project.png)
-### Note
-Milestones and wiki pages are not imported from Bitbucket.
+1. Click on the "Bitbucket" button
+
+ ![Bitbucket](img/import_projects_from_new_project_page.png)
+
+1. Grant GitLab access to your Bitbucket account
+
+ ![Grant access](img/bitbucket_import_grant_access.png)
+
+1. Click on the projects that you'd like to import or **Import all projects**.
+ You can also select the namespace under which each project will be
+ imported.
+
+ ![Import projects](img/bitbucket_import_select_project.png)
+
+[bb-import]: ../../integration/bitbucket.md
+[social sign-in]: ../../user/profile/account/social_sign_in.md
diff --git a/doc/workflow/importing/import_projects_from_gitea.md b/doc/workflow/importing/import_projects_from_gitea.md
new file mode 100644
index 00000000000..f5746a0fb31
--- /dev/null
+++ b/doc/workflow/importing/import_projects_from_gitea.md
@@ -0,0 +1,77 @@
+# Import your project from Gitea to GitLab
+
+Import your projects from Gitea to GitLab with minimal effort.
+
+## Overview
+
+>**Note:**
+This requires Gitea `v1.0.0` or newer.
+
+- At its current state, Gitea importer can import:
+ - the repository description (GitLab 8.15+)
+ - the Git repository data (GitLab 8.15+)
+ - the issues (GitLab 8.15+)
+ - the pull requests (GitLab 8.15+)
+ - the milestones (GitLab 8.15+)
+ - the labels (GitLab 8.15+)
+- Repository public access is retained. If a repository is private in Gitea
+ it will be created as private in GitLab as well.
+
+## How it works
+
+Since Gitea is currently not an OAuth provider, author/assignee cannot be mapped
+to users in your GitLab's instance. This means that the project creator (most of
+the times the current user that started the import process) is set as the author,
+but a reference on the issue about the original Gitea author is kept.
+
+The importer will create any new namespaces (groups) if they don't exist or in
+the case the namespace is taken, the repository will be imported under the user's
+namespace that started the import process.
+
+## Importing your Gitea repositories
+
+The importer page is visible when you create a new project.
+
+![New project page on GitLab](img/import_projects_from_new_project_page.png)
+
+Click on the **Gitea** link and the import authorization process will start.
+
+![New Gitea project import](img/import_projects_from_gitea_new_import.png)
+
+### Authorize access to your repositories using a personal access token
+
+With this method, you will perform a one-off authorization with Gitea to grant
+GitLab access your repositories:
+
+1. Go to <https://you-gitea-instance/user/settings/applications> (replace
+ `you-gitea-instance` with the host of your Gitea instance).
+1. Click **Generate New Token**.
+1. Enter a token description.
+1. Click **Generate Token**.
+1. Copy the token hash.
+1. Go back to GitLab and provide the token to the Gitea importer.
+1. Hit the **List Your Gitea Repositories** button and wait while GitLab reads
+ your repositories' information. Once done, you'll be taken to the importer
+ page to select the repositories to import.
+
+### Select which repositories to import
+
+After you've authorized access to your Gitea repositories, you will be
+redirected to the Gitea importer page.
+
+From there, you can see the import statuses of your Gitea repositories.
+
+- Those that are being imported will show a _started_ status,
+- those already successfully imported will be green with a _done_ status,
+- whereas those that are not yet imported will have an **Import** button on the
+ right side of the table.
+
+If you want, you can import all your Gitea projects in one go by hitting
+**Import all projects** in the upper left corner.
+
+![Gitea importer page](img/import_projects_from_github_importer.png)
+
+---
+
+You can also choose a different name for the project and a different namespace,
+if you have the privileges to do so.
diff --git a/doc/workflow/importing/import_projects_from_github.md b/doc/workflow/importing/import_projects_from_github.md
index c36dfdb78ec..8ed1d98d05b 100644
--- a/doc/workflow/importing/import_projects_from_github.md
+++ b/doc/workflow/importing/import_projects_from_github.md
@@ -6,8 +6,14 @@ Import your projects from GitHub to GitLab with minimal effort.
>**Note:**
If you are an administrator you can enable the [GitHub integration][gh-import]
-in your GitLab instance sitewide. This configuration is optional, users will be
-able import their GitHub repositories with a [personal access token][gh-token].
+in your GitLab instance sitewide. This configuration is optional, users will
+still be able to import their GitHub repositories with a
+[personal access token][gh-token].
+
+>**Note:**
+Administrators of a GitLab instance (Community or Enterprise Edition) can also
+use the [GitHub rake task][gh-rake] to import projects from GitHub without the
+constrains of a Sidekiq worker.
- At its current state, GitHub importer can import:
- the repository description (GitLab 7.7+)
@@ -27,7 +33,7 @@ able import their GitHub repositories with a [personal access token][gh-token].
When issues/pull requests are being imported, the GitHub importer tries to find
the GitHub author/assignee in GitLab's database using the GitHub ID. For this
to work, the GitHub author/assignee should have signed in beforehand in GitLab
-and [**associated their GitHub account**][social sign-in]. If the user is not
+and **associated their GitHub account**. If the user is not
found in GitLab's database, the project creator (most of the times the current
user that started the import process) is set as the author, but a reference on
the issue about the original GitHub author is kept.
@@ -40,7 +46,7 @@ namespace that started the import process.
The importer page is visible when you create a new project.
-![New project page on GitLab](img/import_projects_from_github_new_project_page.png)
+![New project page on GitLab](img/import_projects_from_new_project_page.png)
Click on the **GitHub** link and the import authorization process will start.
There are two ways to authorize access to your GitHub repositories:
@@ -59,8 +65,7 @@ If the [GitHub integration][gh-import] is enabled by your GitLab administrator,
you can use it instead of the personal access token.
1. First you may want to connect your GitHub account to GitLab in order for
- the username mapping to be correct. Follow the [social sign-in] documentation
- on how to do so.
+ the username mapping to be correct.
1. Once you connect GitHub, click the **List your GitHub repositories** button
and you will be redirected to GitHub for permission to access your projects.
1. After accepting, you'll be automatically redirected to the importer.
@@ -85,7 +90,7 @@ authorization with GitHub to grant GitLab access your repositories:
1. Click **Generate token**.
1. Copy the token hash.
1. Go back to GitLab and provide the token to the GitHub importer.
-1. Hit the **List your GitHub repositories** button and wait while GitLab reads
+1. Hit the **List Your GitHub Repositories** button and wait while GitLab reads
your repositories' information. Once done, you'll be taken to the importer
page to select the repositories to import.
@@ -112,7 +117,6 @@ You can also choose a different name for the project and a different namespace,
if you have the privileges to do so.
[gh-import]: ../../integration/github.md "GitHub integration"
-[new-project]: ../../gitlab-basics/create-project.md "How to create a new project in GitLab"
+[gh-rake]: ../../administration/raketasks/github_import.md "GitHub rake task"
[gh-integration]: #authorize-access-to-your-repositories-using-the-github-integration
[gh-token]: #authorize-access-to-your-repositories-using-a-personal-access-token
-[social sign-in]: ../../profile/account/social_sign_in.md
diff --git a/doc/workflow/importing/import_projects_from_gitlab_com.md b/doc/workflow/importing/import_projects_from_gitlab_com.md
index dcc00074b75..b27125a44de 100644
--- a/doc/workflow/importing/import_projects_from_gitlab_com.md
+++ b/doc/workflow/importing/import_projects_from_gitlab_com.md
@@ -5,6 +5,9 @@ GitLab support is enabled on your GitLab instance.
You can read more about GitLab support [here](http://docs.gitlab.com/ce/integration/gitlab.html)
To get to the importer page you need to go to "New project" page.
+>**Note:**
+If you are interested in importing Wiki and Merge Request data to your new instance, you'll need to follow the instructions for [project export](../../user/project/settings/import_export.md)
+
![New project page](gitlab_importer/new_project_page.png)
Click on the "Import projects from GitLab.com" link and you will be redirected to GitLab.com
diff --git a/doc/workflow/importing/migrating_from_svn.md b/doc/workflow/importing/migrating_from_svn.md
index 4828bb5dce6..7a3628a39d7 100644
--- a/doc/workflow/importing/migrating_from_svn.md
+++ b/doc/workflow/importing/migrating_from_svn.md
@@ -4,6 +4,112 @@ Subversion (SVN) is a central version control system (VCS) while
Git is a distributed version control system. There are some major differences
between the two, for more information consult your favorite search engine.
+## Overview
+
+There are two approaches to SVN to Git migration:
+
+1. [Git/SVN Mirror](#smooth-migration-with-a-gitsvn-mirror-using-subgit) which:
+ - Makes the GitLab repository to mirror the SVN project.
+ - Git and SVN repositories are kept in sync; you can use either one.
+ - Smoothens the migration process and allows to manage migration risks.
+
+1. [Cut over migration](#cut-over-migration-with-svn2git) which:
+ - Translates and imports the existing data and history from SVN to Git.
+ - Is a fire and forget approach, good for smaller teams.
+
+## Smooth migration with a Git/SVN mirror using SubGit
+
+[SubGit](https://subgit.com) is a tool for a smooth, stress-free SVN to Git
+migration. It creates a writable Git mirror of a local or remote Subversion
+repository and that way you can use both Subversion and Git as long as you like.
+It requires access to your GitLab server as it talks with the Git repositories
+directly in a filesystem level.
+
+### SubGit prerequisites
+
+1. Install Oracle JRE 1.8 or newer. On Debian-based Linux distributions you can
+ follow [this article](http://www.webupd8.org/2012/09/install-oracle-java-8-in-ubuntu-via-ppa.html).
+1. Download SubGit from https://subgit.com/download/.
+1. Unpack the downloaded SubGit zip archive to the `/opt` directory. The `subgit`
+ command will be available at `/opt/subgit-VERSION/bin/subgit`.
+
+### SubGit configuration
+
+The first step to mirror you SVN repository in GitLab is to create a new empty
+project which will be used as a mirror. For Omnibus installations the path to
+the repository will be located at
+`/var/opt/gitlab/git-data/repositories/USER/REPO.git` by default. For
+installations from source, the default repository directory will be
+`/home/git/repositories/USER/REPO.git`. For convenience, assign this path to a
+variable:
+
+```
+GIT_REPO_PATH=/var/opt/gitlab/git-data/repositories/USER/REPOS.git
+```
+
+SubGit will keep this repository in sync with a remote SVN project. For
+convenience, assign your remote SVN project URL to a variable:
+
+```
+SVN_PROJECT_URL=http://svn.company.com/repos/project
+```
+
+Next you need to run SubGit to set up a Git/SVN mirror. Make sure the following
+`subgit` command is ran on behalf of the same user that keeps ownership of
+GitLab Git repositories (by default `git`):
+
+```
+subgit configure --layout auto $SVN_PROJECT_URL $GIT_REPO_PATH
+```
+
+Adjust authors and branches mappings, if necessary. Open with your favorite
+text editor:
+
+```
+edit $GIT_REPO_PATH/subgit/authors.txt
+edit $GIT_REPO_PATH/subgit/config
+```
+
+For more information regarding the SubGit configuration options, refer to
+[SubGit's documentation](https://subgit.com/documentation.html) website.
+
+### Initial translation
+
+Now that SubGit has configured the Git/SVN repos, run `subgit` to perform the
+initial translation of existing SVN revisions into the Git repository:
+
+```
+subgit install $GIT_REPO_PATH
+```
+
+After the initial translation is completed, the Git repository and the SVN
+project will be kept in sync by `subgit` - new Git commits will be translated to
+SVN revisions and new SVN revisions will be translated to Git commits. Mirror
+works transparently and does not require any special commands.
+
+If you would prefer to perform one-time cut over migration with `subgit`, use
+the `import` command instead of `install`:
+
+```
+subgit import $GIT_REPO_PATH
+```
+
+### SubGit licensing
+
+Running SubGit in a mirror mode requires a
+[registration](https://subgit.com/pricing.html). Registration is free for open
+source, academic and startup projects.
+
+We're currently working on deeper GitLab/SubGit integration. You may track our
+progress at [this issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/990).
+
+### SubGit support
+
+For any questions related to SVN to GitLab migration with SubGit, you can
+contact the SubGit team directly at [support@subgit.com](mailto:support@subgit.com).
+
+## Cut over migration with svn2git
+
If you are currently using an SVN repository, you can migrate the repository
to Git and GitLab. We recommend a hard cut over - run the migration command once
and then have all developers start using the new GitLab repository immediately.
@@ -75,5 +181,3 @@ git push --tags origin
## Contribute to this guide
We welcome all contributions that would expand this guide with instructions on
how to migrate from SVN and other version control systems.
-
-
diff --git a/doc/workflow/lfs/lfs_administration.md b/doc/workflow/lfs/lfs_administration.md
index b3c73e947f0..d768b73286d 100644
--- a/doc/workflow/lfs/lfs_administration.md
+++ b/doc/workflow/lfs/lfs_administration.md
@@ -40,10 +40,18 @@ In `config/gitlab.yml`:
storage_path: /mnt/storage/lfs-objects
```
+## Storage statistics
+
+You can see the total storage used for LFS objects on groups and projects
+in the administration area, as well as through the [groups](../../api/groups.md)
+and [projects APIs](../../api/projects.md).
+
## Known limitations
* Currently, storing GitLab Git LFS objects on a non-local storage (like S3 buckets)
is not supported
-* Currently, removing LFS objects from GitLab Git LFS storage is not supported
+* Support for removing unreferenced LFS objects was added in 8.14 onwards.
* LFS authentications via SSH was added with GitLab 8.12
* Only compatible with the GitLFS client versions 1.1.0 and up, or 1.0.2.
+* The storage statistics currently count each LFS object multiple times for
+ every project linking to it
diff --git a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
index 1a4f213a792..6adde447975 100644
--- a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
+++ b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
@@ -4,13 +4,6 @@ Managing large files such as audio, video and graphics files has always been one
of the shortcomings of Git. The general recommendation is to not have Git repositories
larger than 1GB to preserve performance.
-GitLab already supports [managing large files with git annex](http://docs.gitlab.com/ee/workflow/git_annex.html)
-(EE only), however in certain environments it is not always convenient to use
-different commands to differentiate between the large files and regular ones.
-
-Git LFS makes this simpler for the end user by removing the requirement to
-learn new commands.
-
## How it works
Git LFS client talks with the GitLab server over HTTPS. It uses HTTP Basic Authentication
@@ -24,6 +17,7 @@ Documentation for GitLab instance administrators is under [LFS administration do
## Requirements
* Git LFS is supported in GitLab starting with version 8.2
+* Git LFS must be enabled under project settings
* [Git LFS client](https://git-lfs.github.com) version 1.0.1 and up
## Known limitations
@@ -31,10 +25,10 @@ Documentation for GitLab instance administrators is under [LFS administration do
* Git LFS v1 original API is not supported since it was deprecated early in LFS
development
* When SSH is set as a remote, Git LFS objects still go through HTTPS
-* Any Git LFS request will ask for HTTPS credentials to be provided so good Git
+* Any Git LFS request will ask for HTTPS credentials to be provided so a good Git
credentials store is recommended
* Git LFS always assumes HTTPS so if you have GitLab server on HTTP you will have
- to add the URL to Git config manually (see #troubleshooting)
+ to add the URL to Git config manually (see [troubleshooting](#troubleshooting))
>**Note**: With 8.12 GitLab added LFS support to SSH. The Git LFS communication
still goes over HTTP, but now the SSH client passes the correct credentials
@@ -48,7 +42,7 @@ check it into your Git repository:
```bash
git clone git@gitlab.example.com:group/project.git
-git lfs install # initialize the Git LFS project project
+git lfs install # initialize the Git LFS project
git lfs track "*.iso" # select the file extensions that you want to treat as large files
```
@@ -62,6 +56,12 @@ git commit -am "Added Debian iso" # commit the file meta data
git push origin master # sync the git repo and large file to the GitLab server
```
+>**Note**: Make sure that `.gitattributes` is tracked by git. Otherwise Git
+ LFS will not be working properly for people cloning the project.
+ ```bash
+ git add .gitattributes
+ ```
+
Cloning the repository works the same as before. Git automatically detects the
LFS-tracked files and clones them via HTTP. If you performed the git clone
command with a SSH URL, you have to enter your GitLab credentials for HTTP
@@ -95,7 +95,7 @@ available to the project anymore. Probably the object was removed from the serve
* Local git repository is using deprecated LFS API
-### Invalid status for <url> : 501
+### Invalid status for `<url>` : 501
Git LFS will log the failures into a log file.
To view this log file, while in project directory:
@@ -106,6 +106,9 @@ git lfs logs last
If the status `error 501` is shown, it is because:
+* Git LFS is not enabled in project settings. Check your project settings and
+ enable Git LFS.
+
* Git LFS support is not enabled on the GitLab server. Check with your GitLab
administrator why Git LFS is not enabled on the server. See
[LFS administration documentation](lfs_administration.md) for instructions
@@ -130,7 +133,6 @@ This behaviour is caused by Git LFS using HTTPS connections by default when a
To prevent this from happening, set the lfs url in project Git config:
```bash
-
git config --add lfs.url "http://gitlab.example.com/group/project.git/info/lfs"
```
diff --git a/doc/workflow/merge_commits.png b/doc/workflow/merge_commits.png
index 8aa1587cde6..4a80811c6e3 100644
--- a/doc/workflow/merge_commits.png
+++ b/doc/workflow/merge_commits.png
Binary files differ
diff --git a/doc/workflow/merge_request.png b/doc/workflow/merge_request.png
index 6aad1d82f6e..08dfc7f2468 100644
--- a/doc/workflow/merge_request.png
+++ b/doc/workflow/merge_request.png
Binary files differ
diff --git a/doc/workflow/merge_when_build_succeeds.md b/doc/workflow/merge_when_build_succeeds.md
index 95afd12ebdb..b4f6d6117de 100644
--- a/doc/workflow/merge_when_build_succeeds.md
+++ b/doc/workflow/merge_when_build_succeeds.md
@@ -1 +1 @@
-This document was moved to [user/project/merge_requests/merge_when_build_succeeds](../user/project/merge_requests/merge_when_build_succeeds.md).
+This document was moved to [merge_when_pipeline_succeeds](../user/project/merge_requests/merge_when_pipeline_succeeds.md).
diff --git a/doc/workflow/messy_flow.png b/doc/workflow/messy_flow.png
index 8d2c0dae8c2..7e72e2a3be6 100644
--- a/doc/workflow/messy_flow.png
+++ b/doc/workflow/messy_flow.png
Binary files differ
diff --git a/doc/workflow/milestones.md b/doc/workflow/milestones.md
index dff36899aec..69eb6b286b0 100644
--- a/doc/workflow/milestones.md
+++ b/doc/workflow/milestones.md
@@ -1,13 +1 @@
-# Milestones
-
-Milestones allow you to organize issues and merge requests into a cohesive group, optionally setting a due date.
-A common use is keeping track of an upcoming software version. Milestones are created per-project.
-
-![milestone form](milestones/form.png)
-
-## Groups and milestones
-
-You can create a milestone for several projects in the same group simultaneously.
-On the group's milestones page, you will be able to see the status of that milestone across all of the selected projects.
-
-![group milestone form](milestones/group_form.png)
+This document was moved to [another location](../user/project/milestones/index.md).
diff --git a/doc/workflow/milestones/form.png b/doc/workflow/milestones/form.png
deleted file mode 100644
index 3965ca4d083..00000000000
--- a/doc/workflow/milestones/form.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/milestones/group_form.png b/doc/workflow/milestones/group_form.png
deleted file mode 100644
index ff20df8081f..00000000000
--- a/doc/workflow/milestones/group_form.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/mr_inline_comments.png b/doc/workflow/mr_inline_comments.png
index af7df3100d0..6a2e66a01ba 100644
--- a/doc/workflow/mr_inline_comments.png
+++ b/doc/workflow/mr_inline_comments.png
Binary files differ
diff --git a/doc/workflow/notifications.md b/doc/workflow/notifications.md
index 1b49a5c385f..3e2e7d0f7b6 100644
--- a/doc/workflow/notifications.md
+++ b/doc/workflow/notifications.md
@@ -6,7 +6,7 @@ GitLab has a notification system in place to notify a user of events that are im
You can find notification settings under the user profile.
-![notification settings](notifications/settings.png)
+![notification settings](img/notification_global_settings.png)
Notification settings are divided into three groups:
@@ -32,19 +32,23 @@ anything that is set at Global Settings.
#### Group Settings
+![notification settings](img/notification_group_settings.png)
+
Group Settings are taking precedence over Global Settings but are on a level below Project Settings.
This means that you can set a different level of notifications per group while still being able
to have a finer level setting per project.
Organization like this is suitable for users that belong to different groups but don't have the
same need for being notified for every group they are member of.
-These settings can be configured on group page or user profile notifications dropdown.
+These settings can be configured on group page under the name of the group. It will be the dropdown with the bell icon. They can also be configured on the user profile notifications dropdown.
#### Project Settings
+![notification settings](img/notification_project_settings.png)
+
Project Settings are at the top level and any setting placed at this level will take precedence of any
other setting.
This is suitable for users that have different needs for notifications per project basis.
-These settings can be configured on project page or user profile notifications dropdown.
+These settings can be configured on project page under the name of the project. It will be the dropdown with the bell icon. They can also be configured on the user profile notifications dropdown.
## Notification events
@@ -88,6 +92,8 @@ In all of the below cases, the notification will be sent to:
| Reopen merge request | |
| Merge merge request | |
| New comment | The above, plus anyone mentioned by `@username` in the comment, with notification level "Mention" or higher |
+| Failed pipeline | The author of the pipeline |
+| Successful pipeline | The author of the pipeline, if they have the custom notification setting for successful pipelines set |
In addition, if the title or description of an Issue or Merge Request is
diff --git a/doc/workflow/notifications/settings.png b/doc/workflow/notifications/settings.png
deleted file mode 100644
index d50757beffc..00000000000
--- a/doc/workflow/notifications/settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/production_branch.png b/doc/workflow/production_branch.png
index d88a3687151..648d5d5c92e 100644
--- a/doc/workflow/production_branch.png
+++ b/doc/workflow/production_branch.png
Binary files differ
diff --git a/doc/workflow/project_features.md b/doc/workflow/project_features.md
index f19e7df8c9a..3f5de2bd4b1 100644
--- a/doc/workflow/project_features.md
+++ b/doc/workflow/project_features.md
@@ -26,6 +26,8 @@ This is a separate system for documentation, built right into GitLab.
It is source controlled and is very convenient if you don't want to keep you documentation in your source code, but you do want to keep it in your GitLab project.
+[Read more about Wikis.](../user/project/wiki/index.md)
+
## Snippets
Snippets are little bits of code or text.
diff --git a/doc/workflow/rebase.png b/doc/workflow/rebase.png
index df353311fa0..8b9bb61a5cc 100644
--- a/doc/workflow/rebase.png
+++ b/doc/workflow/rebase.png
Binary files differ
diff --git a/doc/workflow/release_branches.png b/doc/workflow/release_branches.png
index c2162248d25..5194d75a667 100644
--- a/doc/workflow/release_branches.png
+++ b/doc/workflow/release_branches.png
Binary files differ
diff --git a/doc/workflow/releases/new_tag.png b/doc/workflow/releases/new_tag.png
index 2456a8500f4..97519e5808f 100644
--- a/doc/workflow/releases/new_tag.png
+++ b/doc/workflow/releases/new_tag.png
Binary files differ
diff --git a/doc/workflow/releases/tags.png b/doc/workflow/releases/tags.png
index eeda967afd6..4c032f96125 100644
--- a/doc/workflow/releases/tags.png
+++ b/doc/workflow/releases/tags.png
Binary files differ
diff --git a/doc/workflow/remove_checkbox.png b/doc/workflow/remove_checkbox.png
index 3b0393deb0f..fb0e792b37b 100644
--- a/doc/workflow/remove_checkbox.png
+++ b/doc/workflow/remove_checkbox.png
Binary files differ
diff --git a/doc/workflow/shortcuts.md b/doc/workflow/shortcuts.md
index 36516883ef6..87416008e98 100644
--- a/doc/workflow/shortcuts.md
+++ b/doc/workflow/shortcuts.md
@@ -6,7 +6,10 @@ You can see GitLab's keyboard shortcuts by using 'shift + ?'
| Keyboard Shortcut | Description |
| ----------------- | ----------- |
+| <kbd>n</kbd> | Main navigation |
| <kbd>s</kbd> | Focus search |
+| <kbd>f</kbd> | Focus filter |
+| <kbd>p b</kbd> | Show/hide the Performance Bar |
| <kbd>?</kbd> | Show/hide this dialog |
| <kbd>⌘</kbd> + <kbd>shift</kbd> + <kbd>p</kbd> | Toggle markdown preview |
| <kbd>↑</kbd> | Edit last comment (when focused on an empty textarea) |
@@ -36,6 +39,7 @@ You can see GitLab's keyboard shortcuts by using 'shift + ?'
| <kbd>g</kbd> + <kbd>p</kbd> | Go to projects |
| <kbd>g</kbd> + <kbd>i</kbd> | Go to issues |
| <kbd>g</kbd> + <kbd>m</kbd> | Go to merge requests |
+| <kbd>g</kbd> + <kbd>t</kbd> | Go to todos |
## Project
@@ -45,9 +49,9 @@ You can see GitLab's keyboard shortcuts by using 'shift + ?'
| <kbd>g</kbd> + <kbd>e</kbd> | Go to the project's activity feed |
| <kbd>g</kbd> + <kbd>f</kbd> | Go to files |
| <kbd>g</kbd> + <kbd>c</kbd> | Go to commits |
-| <kbd>g</kbd> + <kbd>b</kbd> | Go to builds |
+| <kbd>g</kbd> + <kbd>b</kbd> | Go to jobs |
| <kbd>g</kbd> + <kbd>n</kbd> | Go to network graph |
-| <kbd>g</kbd> + <kbd>g</kbd> | Go to graphs |
+| <kbd>g</kbd> + <kbd>g</kbd> | Go to repository charts |
| <kbd>g</kbd> + <kbd>i</kbd> | Go to issues |
| <kbd>g</kbd> + <kbd>m</kbd> | Go to merge requests |
| <kbd>g</kbd> + <kbd>s</kbd> | Go to snippets |
@@ -73,4 +77,10 @@ You can see GitLab's keyboard shortcuts by using 'shift + ?'
| <kbd>m</kbd> | Change milestone |
| <kbd>r</kbd> | Reply (quoting selected text) |
| <kbd>e</kbd> | Edit issue/merge request |
-| <kbd>l</kbd> | Change label | \ No newline at end of file
+| <kbd>l</kbd> | Change label |
+
+## Wiki pages
+
+| Keyboard Shortcut | Description |
+| ----------------- | ----------- |
+| <kbd>e</kbd> | Edit wiki page|
diff --git a/doc/workflow/time-tracking/time-tracking-example.png b/doc/workflow/time-tracking/time-tracking-example.png
new file mode 100644
index 00000000000..bbcabb602d6
--- /dev/null
+++ b/doc/workflow/time-tracking/time-tracking-example.png
Binary files differ
diff --git a/doc/workflow/time-tracking/time-tracking-sidebar.png b/doc/workflow/time-tracking/time-tracking-sidebar.png
new file mode 100644
index 00000000000..d1ff5571f95
--- /dev/null
+++ b/doc/workflow/time-tracking/time-tracking-sidebar.png
Binary files differ
diff --git a/doc/workflow/time_tracking.md b/doc/workflow/time_tracking.md
new file mode 100644
index 00000000000..bfe87bb2ceb
--- /dev/null
+++ b/doc/workflow/time_tracking.md
@@ -0,0 +1,73 @@
+# Time Tracking
+
+> Introduced in GitLab 8.14.
+
+Time Tracking allows you to track estimates and time spent on issues and merge
+requests within GitLab.
+
+## Overview
+
+Time Tracking lets you:
+* record the time spent working on an issue or a merge request,
+* add an estimate of the amount of time needed to complete an issue or a merge
+request.
+
+You don't have to indicate an estimate to enter the time spent, and vice versa.
+
+Data about time tracking is shown on the issue/merge request sidebar, as shown
+below.
+
+![Time tracking in the sidebar](time-tracking/time-tracking-sidebar.png)
+
+## How to enter data
+
+Time Tracking uses two [quick actions] that GitLab introduced with this new
+feature: `/spend` and `/estimate`.
+
+Quick actions can be used in the body of an issue or a merge request, but also
+in a comment in both an issue or a merge request.
+
+Below is an example of how you can use those new quick actions inside a comment.
+
+![Time tracking example in a comment](time-tracking/time-tracking-example.png)
+
+Adding time entries (time spent or estimates) is limited to project members.
+
+### Estimates
+
+To enter an estimate, write `/estimate`, followed by the time. For example, if
+you need to enter an estimate of 3 days, 5 hours and 10 minutes, you would write
+`/estimate 3d 5h 10m`.
+
+Every time you enter a new time estimate, any previous time estimates will be
+overridden by this new value. There should only be one valid estimate in an
+issue or a merge request.
+
+To remove an estimation entirely, use `/remove_estimation`.
+
+### Time spent
+
+To enter a time spent, use `/spend 3d 5h 10m`.
+
+Every new time spent entry will be added to the current total time spent for the
+issue or the merge request.
+
+You can remove time by entering a negative amount: `/spend -3d` will remove 3
+days from the total time spent. You can't go below 0 minutes of time spent,
+so GitLab will automatically reset the time spent if you remove a larger amount
+of time compared to the time that was entered already.
+
+To remove all the time spent at once, use `/remove_time_spent`.
+
+## Configuration
+
+The following time units are available:
+* weeks (w)
+* days (d)
+* hours (h)
+* minutes (m)
+
+Default conversion rates are 1w = 5d and 1d = 8h.
+
+[landing]: https://about.gitlab.com/features/time-tracking
+[quick actions]: ../user/project/quick_actions.md
diff --git a/doc/workflow/todos.md b/doc/workflow/todos.md
index a50ba305deb..3d8d3ce8f13 100644
--- a/doc/workflow/todos.md
+++ b/doc/workflow/todos.md
@@ -16,7 +16,8 @@ in a simple dashboard.
You can quickly access the Todos dashboard using the bell icon next to the
search bar in the upper right corner. The number in blue is the number of Todos
-you still have open.
+you still have open if the count is < 100, else it's 99+. The exact number
+will still be shown in the body of the _To do_ tab.
![Todos icon](img/todos_icon.png)
@@ -24,16 +25,41 @@ you still have open.
A Todo appears in your Todos dashboard when:
-- an issue or merge request is assigned to you
+- an issue or merge request is assigned to you,
- you are `@mentioned` in an issue or merge request, be it the description of
- the issue/merge request or in a comment
+ the issue/merge request or in a comment,
+- a job in the CI pipeline running for your merge request failed, but this
+ job is not allowed to fail.
>**Note:** Commenting on a commit will _not_ trigger a Todo.
+### Directly addressed Todos
+
+> [Introduced][ce-7926] in GitLab 9.0.
+
+If you are mentioned at the start of a line, the todo you receive will be listed
+as 'directly addressed'. For instance, in this comment:
+
+```markdown
+@alice What do you think? cc: @bob
+
+- @carol can you please have a look?
+
+>>>
+@dan what do you think?
+>>>
+
+@erin @frank thank you!
+```
+
+The people receiving directly addressed todos are `@alice`, `@erin`, and
+`@frank`. Directly addressed todos only differ from mention todos in their type,
+for filtering; otherwise, they appear as normal.
+
### Manually creating a Todo
You can also add an issue or merge request to your Todos dashboard by clicking
-the "Add Todo" button in the issue or merge request sidebar.
+the "Add todo" button in the issue or merge request sidebar.
![Adding a Todo from the issuable sidebar](img/todos_add_todo_sidebar.png)
@@ -67,7 +93,7 @@ corresponding **Done** button, and it will disappear from your Todo list.
![A Todo in the Todos dashboard](img/todo_list_item.png)
A Todo can also be marked as done from the issue or merge request sidebar using
-the "Mark Done" button.
+the "Mark done" button.
![Mark Done from the issuable sidebar](img/todos_mark_done_sidebar.png)
@@ -83,8 +109,9 @@ There are four kinds of filters you can use on your Todos dashboard.
| Project | Filter by project |
| Author | Filter by the author that triggered the Todo |
| Type | Filter by issue or merge request |
-| Action | Filter by the action that triggered the Todo (Assigned or Mentioned)|
+| Action | Filter by the action that triggered the Todo |
-You can also filter by more than one of these at the same time.
+You can also filter by more than one of these at the same time. The possible Actions are `Any Action`, `Assigned`, `Mentioned`, `Added`, `Pipelines`, and `Directly Addressed`, [as described above](#what-triggers-a-todo).
[ce-2817]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2817
+[ce-7926]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7926