diff options
38 files changed, 561 insertions, 127 deletions
diff --git a/CHANGELOG b/CHANGELOG index 20a21abfb69..00822465e3a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,10 +1,15 @@ Please view this file on the master branch, on stable branches it's out of date. -v 8.6.0 (unreleased) +v 8.7.0 (unreleased) + - Make HTTP(s) label consistent on clone bar (Stan Hu) + +v 8.6.1 (unreleased) + + +v 8.6.0 - Add ability to move issue to another project - Prevent tokens in the import URL to be showed by the UI - Fix bug where wrong commit ID was being used in a merge request diff to show old image (Stan Hu) - - Make HTTP(s) label consistent on clone bar (Stan Hu) - Add confidential issues - Bump gitlab_git to 9.0.3 (Stan Hu) - Fix diff image view modes (2-up, swipe, onion skin) not working (Stan Hu) @@ -19,11 +24,14 @@ v 8.6.0 (unreleased) setup. A password can be provided during setup (see installation docs), or GitLab will ask the user to create a new one upon first visit. - Fix issue when pushing to projects ending in .wiki + - Properly display YAML front matter in Markdown - Add support for wiki with UTF-8 page names (Hiroyuki Sato) - Fix wiki search results point to raw source (Hiroyuki Sato) - Don't load all of GitLab in mail_room + - Add information about `image` and `services` field at `job` level in the `.gitlab-ci.yml` documentation (Pat Turner) - HTTP error pages work independently from location and config (Artem Sidorenko) - Update `omniauth-saml` to 1.5.0 to allow for custom response attributes to be set + - Add option to reload the schema before restoring a database backup. !2807 - Memoize @group in Admin::GroupsController (Yatish Mehta) - Indicate how much an MR diverged from the target branch (Pierre de La Morinerie) - Added omniauth-auth0 Gem (Daniel Carraro) diff --git a/app/assets/javascripts/api.js.coffee b/app/assets/javascripts/api.js.coffee index 2ddf8612db3..f3ed9a66715 100644 --- a/app/assets/javascripts/api.js.coffee +++ b/app/assets/javascripts/api.js.coffee @@ -74,6 +74,8 @@ dataType: "json" ).done (label) -> callback(label) + .error (message) -> + callback(message.responseJSON) # Return group projects list. Filtered by query groupProjects: (group_id, query, callback) -> diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 01451830653..3c83450ce18 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -218,13 +218,20 @@ $ -> $this = $(this) $this.attr 'value', $this.val() + $sidebarGutterToggle = $('.js-sidebar-toggle') + $navIconToggle = $('.toggle-nav-collapse') + $(document) .off 'breakpoint:change' .on 'breakpoint:change', (e, breakpoint) -> if breakpoint is 'sm' or breakpoint is 'xs' - $gutterIcon = $('.js-sidebar-toggle').find('i') + $gutterIcon = $sidebarGutterToggle.find('i') if $gutterIcon.hasClass('fa-angle-double-right') - $gutterIcon.closest('a').trigger('click') + $sidebarGutterToggle.trigger('click') + + $navIcon = $navIconToggle.find('.fa') + if $navIcon.hasClass('fa-angle-left') + $navIconToggle.trigger('click') $(document) .off 'click', '.js-sidebar-toggle' diff --git a/app/assets/javascripts/labels_select.js.coffee b/app/assets/javascripts/labels_select.js.coffee index 4a0c18a99a6..f3cb1e3bc09 100644 --- a/app/assets/javascripts/labels_select.js.coffee +++ b/app/assets/javascripts/labels_select.js.coffee @@ -14,6 +14,9 @@ class @LabelsSelect defaultLabel = $dropdown.data('default-label') if newLabelField.length + $newLabelError = $dropdown.parent().find('.js-label-error') + $newLabelError.hide() + $('.suggest-colors-dropdown a').on 'click', (e) -> e.preventDefault() e.stopPropagation() @@ -27,6 +30,7 @@ class @LabelsSelect e.stopPropagation() if newLabelField.val() isnt '' and newColorField.val() isnt '' + $newLabelError.hide() $('.js-new-label-btn').disable() # Create new label with API @@ -35,7 +39,13 @@ class @LabelsSelect color: newColorField.val() }, (label) -> $('.js-new-label-btn').enable() - $('.dropdown-menu-back', $dropdown.parent()).trigger 'click' + + if label.message? + $newLabelError + .text label.message + .show() + else + $('.dropdown-menu-back', $dropdown.parent()).trigger 'click' $dropdown.glDropdown( data: (term, callback) -> diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 1f770876464..8625817fdab 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -378,7 +378,6 @@ table { position: absolute; top: 0; right: 0; - width: 250px !important; visibility: hidden; } } diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss index 40a508c1ebc..99e49a70923 100644 --- a/app/assets/stylesheets/framework/filters.scss +++ b/app/assets/stylesheets/framework/filters.scss @@ -11,3 +11,11 @@ } } } + +@media (max-width: $screen-xs-max) { + .filter-item { + display: block; + margin: 0 0 10px 0; + } +} + diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 5f4ce87b085..625a0bf69c6 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -102,6 +102,10 @@ display: inline-block; } + .icon-label { + display: none; + } + input { height: 34px; display: inline-block; @@ -124,9 +128,38 @@ } } - /* Hide on extra small devices (phones) */ @media (max-width: $screen-xs-max) { - display: none; + padding-bottom: 0; + + .btn, form, .dropdown, .dropdown-menu-toggle, .form-control { + margin: 0 0 10px 0; + display: block; + width: 100%; + } + + form { + display: block; + height: auto; + + input { + width: 100%; + margin: 0 0 10px; + } + } + + .input-short { + width: 100%; + } + + .icon-label { + display: inline-block; + } + + // Applies on /dashboard/issues + .project-item-select-holder { + display: block; + margin: 0; + } } /* Small devices (tablets, 768px and lower) */ diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index be05db58c40..6107c8a6d0a 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -39,7 +39,7 @@ } .sidebar-wrapper { - z-index: 999; + z-index: 1000; background: $background-color; } diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss index 61ee34b695e..3c13573c8fe 100644 --- a/app/assets/stylesheets/pages/labels.scss +++ b/app/assets/stylesheets/pages/labels.scss @@ -45,3 +45,10 @@ .label-subscription { display: inline-block; } + +.dropdown-labels-error { + padding: 5px 10px; + margin-bottom: 10px; + background-color: $gl-danger; + color: $white-light; +} diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index dfa5f80eef8..1eec4db45a0 100644 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -10,6 +10,8 @@ - if current_user = link_to issues_dashboard_url(format: :atom, private_token: current_user.private_token), class: 'btn' do = icon('rss') + %span.icon-label + Subscribe = render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue" = render 'shared/issuable/filter', type: :issues diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml index b0805593fdc..aea35c50862 100644 --- a/app/views/groups/issues.html.haml +++ b/app/views/groups/issues.html.haml @@ -10,6 +10,8 @@ - if current_user = link_to issues_group_url(@group, format: :atom, private_token: current_user.private_token), class: 'btn' do = icon('rss') + %span.icon-label + Subscribe = render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue" = render 'shared/issuable/filter', type: :issues diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index fde9304c0f8..efa7642b2dc 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -11,6 +11,8 @@ - if current_user = link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do = icon('rss') + %span.icon-label + Subscribe = render 'shared/issuable/search_form', path: namespace_project_issues_path(@project.namespace, @project) - if can? current_user, :create_issue, @project = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new", title: "New Issue", id: "new_issue_link" do diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml index ac20f7d1f7e..53952e608ea 100644 --- a/app/views/shared/issuable/_filter.html.haml +++ b/app/views/shared/issuable/_filter.html.haml @@ -42,7 +42,7 @@ placeholder: "Search authors", data: { first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: @project.id, field_name: "update[assignee_id]" } }) .filter-item.inline = dropdown_tag("Milestone", options: { title: "Assign milestone", toggle_class: 'js-milestone-select', filter: true, dropdown_class: "dropdown-menu-selectable", - placeholder: "Search milestones", data: { show_no: true, field_name: "update[milestone_id]", project_id: @project.id, milestones: namespace_project_milestones_path(@project.namespace, @project, :js), use_id: true } }) + placeholder: "Search milestones", data: { show_no: true, field_name: "update[milestone_id]", project_id: @project.id, milestones: namespace_project_milestones_path(@project.namespace, @project, :json), use_id: true } }) = hidden_field_tag 'update[issues_ids]', [] = hidden_field_tag :state_event, params[:state_event] .filter-item.inline diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 551f0cc0b51..b01a36265f9 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -131,7 +131,8 @@ - else .pull-right - if current_user.can?(:"destroy_#{issuable.to_ability_name}", @project) - = link_to polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), method: :delete, class: 'btn btn-grouped' do + = link_to polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), data: { confirm: "#{issuable.class.name.titleize} will be removed! Are you sure?" }, + method: :delete, class: 'btn btn-grouped' do = icon('trash-o') Delete = link_to 'Cancel', namespace_project_issue_path(@project.namespace, @project, issuable), class: 'btn btn-grouped btn-cancel' diff --git a/app/views/shared/issuable/_label_dropdown.html.haml b/app/views/shared/issuable/_label_dropdown.html.haml index 87617315181..186087e8f89 100644 --- a/app/views/shared/issuable/_label_dropdown.html.haml +++ b/app/views/shared/issuable/_label_dropdown.html.haml @@ -27,6 +27,7 @@ .dropdown-page-two = dropdown_title("Create new label", back: true) = dropdown_content do + .dropdown-labels-error.js-label-error %input#new_label_color{type: "hidden"} %input#new_label_name.dropdown-input-field{type: "text", placeholder: "Name new label"} .dropdown-label-color-preview.js-dropdown-label-color-preview diff --git a/doc/gitlab-basics/README.md b/doc/gitlab-basics/README.md index 493e1d1b09c..3aa83975ace 100644 --- a/doc/gitlab-basics/README.md +++ b/doc/gitlab-basics/README.md @@ -2,26 +2,14 @@ Step-by-step guides on the basics of working with Git and GitLab. -* [Start using Git on the command line](start-using-git.md) - -* [Create and add your SSH Keys](create-your-ssh-keys.md) - -* [Command Line basic commands](command-line-commands.md) - -* [Basic Git commands](basic-git-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) +- [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) diff --git a/doc/gitlab-basics/basic-git-commands.md b/doc/gitlab-basics/basic-git-commands.md index 2b5767dd2d3..c2a3415cbc4 100644 --- a/doc/gitlab-basics/basic-git-commands.md +++ b/doc/gitlab-basics/basic-git-commands.md @@ -1,59 +1,3 @@ # Basic Git commands -### Go to the master branch to pull the latest changes from there -``` -git checkout master -``` - -### Download the latest changes in the project -This is for you to work on an up-to-date copy (it is important to do every time you work on a project), while you setup tracking branches. -``` -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. -``` -git checkout -b NAME-OF-BRANCH -``` - -### Work on a branch that has already been created -``` -git checkout NAME-OF-BRANCH -``` - -### View the changes you've made -It's important to be aware of what's happening and what's the status of your changes. -``` -git status -``` - -### Add changes to commit -You'll see your changes in red when you type "git status". -``` -git add CHANGES IN RED -git commit -m "DESCRIBE THE INTENTION OF THE COMMIT" -``` - -### Send changes to gitlab.com -``` -git push REMOTE NAME-OF-BRANCH -``` - -### Delete all changes in the Git repository, but leave unstaged things -``` -git checkout . -``` - -### Delete all changes in the Git repository, including untracked files -``` -git clean -f -``` - -### Merge created branch with master branch -You need to be in the created branch. -``` -git checkout NAME-OF-BRANCH -git merge master -``` +This section is now merged into [Start using Git](start-using-git.md). diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md index b2ceda025c0..89ce8bcc3e8 100644 --- a/doc/gitlab-basics/start-using-git.md +++ b/doc/gitlab-basics/start-using-git.md @@ -1,6 +1,7 @@ # 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 a Git and GitLab, make sure that you have created an +account on GitLab. ## Open a shell @@ -59,3 +60,63 @@ To view the information that you entered, type: ``` git config --global --list ``` +## Basic Git commands + +### Go to the master branch to pull the latest changes from there + +``` +git checkout master +``` + +### Download the latest changes in the project +This is for you to work on an up-to-date copy (it is important to do every time you work on a project), while you setup tracking branches. +``` +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. +``` +git checkout -b NAME-OF-BRANCH +``` + +### Work on a branch that has already been created +``` +git checkout NAME-OF-BRANCH +``` + +### View the changes you've made +It's important to be aware of what's happening and what's the status of your changes. +``` +git status +``` + +### Add changes to commit +You'll see your changes in red when you type "git status". +``` +git add CHANGES IN RED +git commit -m "DESCRIBE THE INTENTION OF THE COMMIT" +``` + +### Send changes to gitlab.com +``` +git push REMOTE NAME-OF-BRANCH +``` + +### Delete all changes in the Git repository, but leave unstaged things +``` +git checkout . +``` + +### Delete all changes in the Git repository, including untracked files +``` +git clean -f +``` + +### Merge created branch with master branch +You need to be in the created branch. +``` +git checkout NAME-OF-BRANCH +git merge master +``` diff --git a/doc/intro/README.md b/doc/intro/README.md new file mode 100644 index 00000000000..fecbbe6317b --- /dev/null +++ b/doc/intro/README.md @@ -0,0 +1,41 @@ +# Get started with GitLab + +## Organize + +Create projects and groups. + +- [Create a new project](../gitlab-basics/create-project.md) +- [Create a new group](../gitlab-basics/create-group.md) + +## Prioritize + +Create issues, labels, milestones, cast your vote, and review issues. + +- [Create a new issue](../gitlab-basics/create-issue.md) +- [Assign labels to issues](../workflow/labels.md) +- [Use milestones as an overview of your project's tracker](../workflow/milestones.md) +- [Use voting to express your like/dislike to issues and merge requests](../workflow/award_emoji.md) + +## Collaborate + +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](../customization/issue_closing.md) +- [Automatically merge when your builds succeed](../workflow/merge_when_build_succeeds.md) +- [Revert any commit](../workflow/revert_changes.md) + +## Test and Deploy + +Use the built-in continuous integration in GitLab. + +- [Get started with GitLab CI](../ci/quick_start/README.md) + +## Install and Update + +Install and update your GitLab installation. + +- [Install GitLab](https://about.gitlab.com/installation/) +- [Update GitLab](https://about.gitlab.com/update/) +- [Explore Omnibus GitLab configuration options](http://doc.gitlab.com/omnibus/settings/configuration.html) diff --git a/doc/monitoring/performance/grafana_configuration.md b/doc/monitoring/performance/grafana_configuration.md new file mode 100644 index 00000000000..416c9870aa0 --- /dev/null +++ b/doc/monitoring/performance/grafana_configuration.md @@ -0,0 +1,118 @@ +# 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 copy and run a set of queries against InfluxDB to create the needed data +sets. + +On the InfluxDB server, run the following command, substituting your InfluxDB +user and password: + +```bash +influxdb --username admin -password super_secret +``` + +This will drop you in to an InfluxDB interactive session. Copy the entire +contents below and paste it in to the interactive session: + +``` +CREATE RETENTION POLICY gitlab_30d ON gitlab DURATION 30d REPLICATION 1 DEFAULT +CREATE RETENTION POLICY seven_days ON gitlab DURATION 7d REPLICATION 1 +CREATE CONTINUOUS QUERY rails_transaction_timings_seven_days ON gitlab BEGIN SELECT percentile("duration", 95.000) AS "duration_95th", percentile("duration", 99.000) AS "duration_99th", mean("duration") AS "duration_mean", percentile(sql_duration, 95.000) AS "sql_duration_95th", percentile(sql_duration, 99.000) AS "sql_duration_99th", mean(sql_duration) AS "sql_duration_mean", percentile(view_duration, 95.000) AS "view_duration_95th", percentile(view_duration, 99.000) AS "view_duration_99th", mean(view_duration) AS "view_duration_mean" INTO gitlab.seven_days.rails_transaction_timings FROM gitlab.gitlab_30d.rails_transactions GROUP BY time(1m) END +CREATE CONTINUOUS QUERY sidekiq_transaction_timings_seven_days ON gitlab BEGIN SELECT percentile("duration", 95.000) AS "duration_95th", percentile("duration", 99.000) AS "duration_99th", mean("duration") AS "duration_mean", percentile(sql_duration, 95.000) AS "sql_duration_95th", percentile(sql_duration, 99.000) AS "sql_duration_99th", mean(sql_duration) AS "sql_duration_mean", percentile(view_duration, 95.000) AS "view_duration_95th", percentile(view_duration, 99.000) AS "view_duration_99th", mean(view_duration) AS "view_duration_mean" INTO gitlab.seven_days.sidekiq_transaction_timings FROM gitlab.gitlab_30d.sidekiq_transactions GROUP BY time(1m) END +CREATE CONTINUOUS QUERY rails_transaction_counts_seven_days ON gitlab BEGIN SELECT count("duration") AS "count" INTO gitlab.seven_days.rails_transaction_counts FROM gitlab.gitlab_30d.rails_transactions GROUP BY time(1m) END +CREATE CONTINUOUS QUERY sidekiq_transaction_counts_seven_days ON gitlab BEGIN SELECT count("duration") AS "count" INTO gitlab.seven_days.sidekiq_transaction_counts FROM gitlab.gitlab_30d.sidekiq_transactions GROUP BY time(1m) END +CREATE CONTINUOUS QUERY rails_method_call_timings_seven_days ON gitlab BEGIN SELECT percentile("duration", 95.000) AS "duration_95th", percentile("duration", 99.000) AS "duration_99th", mean("duration") AS "duration_mean" INTO gitlab.seven_days.rails_method_call_timings FROM gitlab.gitlab_30d.rails_method_calls GROUP BY time(1m) END +CREATE CONTINUOUS QUERY sidekiq_method_call_timings_seven_days ON gitlab BEGIN SELECT percentile("duration", 95.000) AS "duration_95th", percentile("duration", 99.000) AS "duration_99th", mean("duration") AS "duration_mean" INTO gitlab.seven_days.sidekiq_method_call_timings FROM gitlab.gitlab_30d.sidekiq_method_calls GROUP BY time(1m) END +CREATE CONTINUOUS QUERY rails_method_call_timings_per_method_seven_days ON gitlab BEGIN SELECT percentile("duration", 95.000) AS duration_95th, percentile("duration", 99.000) AS duration_99th, mean("duration") AS duration_mean INTO gitlab.seven_days.rails_method_call_timings_per_method FROM gitlab.gitlab_30d.rails_method_calls GROUP BY time(1m), method END +CREATE CONTINUOUS QUERY sidekiq_method_call_timings_per_method_seven_days ON gitlab BEGIN SELECT percentile("duration", 95.000) AS duration_95th, percentile("duration", 99.000) AS duration_99th, mean("duration") AS duration_mean INTO gitlab.seven_days.sidekiq_method_call_timings_per_method FROM gitlab.gitlab_30d.sidekiq_method_calls GROUP BY time(1m), method END +CREATE CONTINUOUS QUERY rails_memory_usage_per_minute ON gitlab BEGIN SELECT percentile(value, 95.000) AS memory_95th, percentile(value, 99.000) AS memory_99th, mean(value) AS memory_mean INTO gitlab.seven_days.rails_memory_usage_per_minute FROM gitlab.gitlab_30d.rails_memory_usage GROUP BY time(1m) END +CREATE CONTINUOUS QUERY sidekiq_memory_usage_per_minute ON gitlab BEGIN SELECT percentile(value, 95.000) AS memory_95th, percentile(value, 99.000) AS memory_99th, mean(value) AS memory_mean INTO gitlab.seven_days.sidekiq_memory_usage_per_minute FROM gitlab.gitlab_30d.sidekiq_memory_usage GROUP BY time(1m) END +CREATE CONTINUOUS QUERY sidekiq_file_descriptors_per_minute ON gitlab BEGIN SELECT sum(value) AS value INTO gitlab.seven_days.sidekiq_file_descriptors_per_minute FROM gitlab.gitlab_30d.sidekiq_file_descriptors GROUP BY time(1m) END +CREATE CONTINUOUS QUERY rails_file_descriptors_per_minute ON gitlab BEGIN SELECT sum(value) AS value INTO gitlab.seven_days.rails_file_descriptors_per_minute FROM gitlab.gitlab_30d.rails_file_descriptors GROUP BY time(1m) END +CREATE CONTINUOUS QUERY rails_gc_counts_per_minute ON gitlab BEGIN SELECT sum(count) AS count INTO gitlab.seven_days.rails_gc_counts_per_minute FROM gitlab.gitlab_30d.rails_gc_statistics GROUP BY time(1m) END +CREATE CONTINUOUS QUERY sidekiq_gc_counts_per_minute ON gitlab BEGIN SELECT sum(count) AS count INTO gitlab.seven_days.sidekiq_gc_counts_per_minute FROM gitlab.gitlab_30d.sidekiq_gc_statistics GROUP BY time(1m) END +CREATE CONTINUOUS QUERY rails_gc_timings_per_minute ON gitlab BEGIN SELECT percentile(total_time, 95.000) AS duration_95th, percentile(total_time, 99.000) AS duration_99th, mean(total_time) AS duration_mean INTO gitlab.seven_days.rails_gc_timings_per_minute FROM gitlab.gitlab_30d.rails_gc_statistics GROUP BY time(1m) END +CREATE CONTINUOUS QUERY sidekiq_gc_timings_per_minute ON gitlab BEGIN SELECT percentile(total_time, 95.000) AS duration_95th, percentile(total_time, 99.000) AS duration_99th, mean(total_time) AS duration_mean INTO gitlab.seven_days.sidekiq_gc_timings_per_minute FROM gitlab.gitlab_30d.sidekiq_gc_statistics GROUP BY time(1m) END +CREATE CONTINUOUS QUERY rails_gc_major_minor_per_minute ON gitlab BEGIN SELECT sum(major_gc_count) AS major, sum(minor_gc_count) AS minor INTO gitlab.seven_days.rails_gc_major_minor_per_minute FROM gitlab.gitlab_30d.rails_gc_statistics GROUP BY time(1m) END +CREATE CONTINUOUS QUERY sidekiq_gc_major_minor_per_minute ON gitlab BEGIN SELECT sum(major_gc_count) AS major, sum(minor_gc_count) AS minor INTO gitlab.seven_days.sidekiq_gc_major_minor_per_minute FROM gitlab.gitlab_30d.sidekiq_gc_statistics GROUP BY time(1m) END +``` + +## 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. + +[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/monitoring/performance/img/grafana_dashboard_dropdown.png b/doc/monitoring/performance/img/grafana_dashboard_dropdown.png Binary files differnew file mode 100644 index 00000000000..b4448c7a09f --- /dev/null +++ b/doc/monitoring/performance/img/grafana_dashboard_dropdown.png diff --git a/doc/monitoring/performance/img/grafana_dashboard_import.png b/doc/monitoring/performance/img/grafana_dashboard_import.png Binary files differnew file mode 100644 index 00000000000..5a2d3c0937a --- /dev/null +++ b/doc/monitoring/performance/img/grafana_dashboard_import.png diff --git a/doc/monitoring/performance/img/grafana_data_source_configuration.png b/doc/monitoring/performance/img/grafana_data_source_configuration.png Binary files differnew file mode 100644 index 00000000000..7e2e111f570 --- /dev/null +++ b/doc/monitoring/performance/img/grafana_data_source_configuration.png diff --git a/doc/monitoring/performance/img/grafana_data_source_empty.png b/doc/monitoring/performance/img/grafana_data_source_empty.png Binary files differnew file mode 100644 index 00000000000..11e27571e64 --- /dev/null +++ b/doc/monitoring/performance/img/grafana_data_source_empty.png diff --git a/doc/monitoring/performance/img/grafana_save_icon.png b/doc/monitoring/performance/img/grafana_save_icon.png Binary files differnew file mode 100644 index 00000000000..3d4265bee8e --- /dev/null +++ b/doc/monitoring/performance/img/grafana_save_icon.png diff --git a/doc/monitoring/performance/introduction.md b/doc/monitoring/performance/introduction.md index f2460d31302..79904916b7e 100644 --- a/doc/monitoring/performance/introduction.md +++ b/doc/monitoring/performance/introduction.md @@ -8,8 +8,9 @@ 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 Configuration](influxdb_configuration.md) +- [InfluxDB Install/Configuration](influxdb_configuration.md) - [InfluxDB Schema](influxdb_schema.md) +- [Grafana Install/Configuration](grafana_configuration.md) ## Introduction to GitLab Performance Monitoring diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md index 6e22ea7b72a..20aa90f0d69 100644 --- a/doc/public_access/public_access.md +++ b/doc/public_access/public_access.md @@ -35,6 +35,21 @@ the repository. 1. Go to your project's **Settings** 1. Change "Visibility Level" to either Public, Internal or Private +## Visibility of groups + +>**Note:** +[Starting with][3323] GitLab 8.6, the group visibility has changed and can be +configured the same way as projects. In previous versions, a group's page was +always visible to all users. + +Like with projects, the visibility of a group can be set to dictate whether +anonymous users, all signed in users, or only explicit group members can view +it. The restriction for visibility levels on the application setting level also +applies to groups, so if that's set to internal, the explore page will be empty +for anonymous users. The group page now has a visibility level icon. + +[3323]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3323 + ## Visibility of users The public page of a user, located at `/u/username`, is always visible whether @@ -43,14 +58,6 @@ you are logged in or not. When visiting the public page of a user, you can only see the projects which you are privileged to. -## Visibility of groups - -The public page of a group, located at `/groups/groupname`, is always visible -to everyone. - -Logged out users will be able to see the description and the avatar of the -group as well as all public projects belonging to that group. - ## Restricting the use of public or internal projects In the Admin area under **Settings** (`/admin/application_settings`), you can diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index f6d1234ac4a..4329ac30a1c 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -249,6 +249,9 @@ reconfigure` after changing `gitlab-secrets.json`. ### Installation from source ``` +# Stop processes that are connected to the database +sudo service gitlab stop + bundle exec rake gitlab:backup:restore RAILS_ENV=production ``` diff --git a/doc/update/README.md b/doc/update/README.md index 109d5de3fa2..0241f036830 100644 --- a/doc/update/README.md +++ b/doc/update/README.md @@ -15,3 +15,4 @@ Depending on the installation method and your GitLab version, there are multiple - [MySQL to PostgreSQL](mysql_to_postgresql.md) guides you through migrating your database from MySQL to PostgreSQL. - [MySQL installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/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) diff --git a/doc/update/restore_after_failure.md b/doc/update/restore_after_failure.md new file mode 100644 index 00000000000..01c52aae7f5 --- /dev/null +++ b/doc/update/restore_after_failure.md @@ -0,0 +1,83 @@ +# Restoring from backup after a failed upgrade + +Upgrades are usually smooth and restoring from backup is a rare occurrence. +However, it's important to know how to recover when problems do arise. + +## Roll back to an earlier version and restore a backup + +In some cases after a failed upgrade, the fastest solution is to roll back to +the previous version you were using. + +First, roll back the code or package. For source installations this involves +checking out the older version (branch or tag). For Omnibus installations this +means installing the older .deb or .rpm package. Then, restore from a backup. +Follow the instructions in the +[Backup and Restore](../raketasks/backup_restore.md#restore-a-previously-created-backup) +documentation. + +## Potential problems on the next upgrade + +When a rollback is necessary it can produce problems on subsequent upgrade +attempts. This is because some tables may have been added during the failed +upgrade. If these tables are still present after you restore from the +older backup it can lead to migration failures on future upgrades. + +Starting in GitLab 8.6 we drop all tables prior to importing the backup to +prevent this problem. If you've restored a backup to a version prior to 8.6 you +may need to manually correct the problem next time you upgrade. + +Example error: + +``` +== 20151103134857 CreateLfsObjects: migrating ================================= +-- create_table(:lfs_objects) +rake aborted! +StandardError: An error has occurred, this and all later migrations canceled: + +PG::DuplicateTable: ERROR: relation "lfs_objects" already exists +``` + +Copy the version from the error. In this case the version number is +`20151103134857`. + +>**WARNING:** Use the following steps only if you are certain this is what you +need to do. + +### GitLab 8.6+ + +Pass the version to a database rake task to manually mark the migration as +complete. + +``` +# Source install +sudo -u git -H bundle exec rake gitlab:db:mark_migration_complete[20151103134857] RAILS_ENV=production + +# Omnibus install +sudo gitlab-rake gitlab:db:mark_migration_complete[20151103134857] +``` + +Once the migration is successfully marked, run the rake `db:migrate` task again. +You will likely have to repeat this process several times until all failed +migrations are marked complete. + +### GitLab < 8.6 + +``` +# Source install +sudo -u git -H bundle exec rails console production + +# Omnibus install +sudo gitlab-rails console +``` + +At the Rails console, type the following commands: + +``` +ActiveRecord::Base.connection.execute("INSERT INTO schema_migrations (version) VALUES('20151103134857')") +exit +``` + +Once the migration is successfully marked, run the rake `db:migrate` task again. +You will likely have to repeat this process several times until all failed +migrations are marked complete. + diff --git a/doc/workflow/award_emoji.md b/doc/workflow/award_emoji.md new file mode 100644 index 00000000000..70b35c58be6 --- /dev/null +++ b/doc/workflow/award_emoji.md @@ -0,0 +1,48 @@ +# Award emojis + +>**Note:** +This feature was [introduced][1825] in GitLab 8.2. + +When you're collaborating online, you get fewer opportunities for high-fives +and thumbs-ups. In order to make virtual celebrations easier, you can now vote +on issues and merge requests using emoji! + +![Award emoji](img/award_emoji_select.png) + +This makes it much easier to give and receive feedback, without a long comment +thread. Any comment that contains only the thumbs up or down emojis is +converted to a vote and depicted in the emoji area. + +You can then use that functionality to sort issues and merge requests based on +popularity. + +## Sort issues and merge requests on vote count + +>**Note:** +This feature was [introduced][2871] in GitLab 8.5. + +You can quickly sort the issues or merge requests by the number of votes they +have received. The sort option can be found in the right dropdown menu. + +![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 number of upvotes and downvotes is not summed up. That means that an issue +with 18 upvotes and 5 downvotes is considered more popular than an issue with +17 upvotes and no downvotes. + +[2871]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2781 +[1825]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/1825 diff --git a/doc/workflow/img/award_emoji_select.png b/doc/workflow/img/award_emoji_select.png Binary files differnew file mode 100644 index 00000000000..fffdfedda5d --- /dev/null +++ b/doc/workflow/img/award_emoji_select.png diff --git a/doc/workflow/img/award_emoji_votes_least_popular.png b/doc/workflow/img/award_emoji_votes_least_popular.png Binary files differnew file mode 100644 index 00000000000..2ef5be7154f --- /dev/null +++ b/doc/workflow/img/award_emoji_votes_least_popular.png diff --git a/doc/workflow/img/award_emoji_votes_most_popular.png b/doc/workflow/img/award_emoji_votes_most_popular.png Binary files differnew file mode 100644 index 00000000000..5b089730d93 --- /dev/null +++ b/doc/workflow/img/award_emoji_votes_most_popular.png diff --git a/doc/workflow/img/award_emoji_votes_sort_options.png b/doc/workflow/img/award_emoji_votes_sort_options.png Binary files differnew file mode 100644 index 00000000000..9bbf3f82a0b --- /dev/null +++ b/doc/workflow/img/award_emoji_votes_sort_options.png diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake index cb4abe13799..402bb338f27 100644 --- a/lib/tasks/gitlab/backup.rake +++ b/lib/tasks/gitlab/backup.rake @@ -22,7 +22,7 @@ namespace :gitlab do end # Restore backup of GitLab system - desc "GitLab | Restore a previously created backup" + desc 'GitLab | Restore a previously created backup' task restore: :environment do warn_user_is_not_gitlab configure_cron_mode @@ -30,13 +30,31 @@ namespace :gitlab do backup = Backup::Manager.new backup.unpack - Rake::Task["gitlab:backup:db:restore"].invoke unless backup.skipped?("db") - Rake::Task["gitlab:backup:repo:restore"].invoke unless backup.skipped?("repositories") - Rake::Task["gitlab:backup:uploads:restore"].invoke unless backup.skipped?("uploads") - Rake::Task["gitlab:backup:builds:restore"].invoke unless backup.skipped?("builds") - Rake::Task["gitlab:backup:artifacts:restore"].invoke unless backup.skipped?("artifacts") - Rake::Task["gitlab:backup:lfs:restore"].invoke unless backup.skipped?("lfs") - Rake::Task["gitlab:shell:setup"].invoke + unless backup.skipped?('db') + unless ENV['force'] == 'yes' + warning = warning = <<-MSG.strip_heredoc + Before restoring the database we recommend removing all existing + tables to avoid future upgrade problems. Be aware that if you have + custom tables in the GitLab database these tables and all data will be + removed. + MSG + ask_to_continue + puts 'Removing all tables. Press `Ctrl-C` within 5 seconds to abort'.yellow + sleep(5) + end + # Drop all tables Load the schema to ensure we don't have any newer tables + # hanging out from a failed upgrade + $progress.puts 'Cleaning the database ... '.blue + Rake::Task['gitlab:db:drop_tables'].invoke + $progress.puts 'done'.green + Rake::Task['gitlab:backup:db:restore'].invoke + end + Rake::Task['gitlab:backup:repo:restore'].invoke unless backup.skipped?('repositories') + Rake::Task['gitlab:backup:uploads:restore'].invoke unless backup.skipped?('uploads') + Rake::Task['gitlab:backup:builds:restore'].invoke unless backup.skipped?('builds') + Rake::Task['gitlab:backup:artifacts:restore'].invoke unless backup.skipped?('artifacts') + Rake::Task['gitlab:backup:lfs:restore'].invoke unless backup.skipped?('lfs') + Rake::Task['gitlab:shell:setup'].invoke backup.cleanup end diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake new file mode 100644 index 00000000000..4921c6e0bcf --- /dev/null +++ b/lib/tasks/gitlab/db.rake @@ -0,0 +1,35 @@ +namespace :gitlab do + namespace :db do + desc 'GitLab | Manually insert schema migration version' + task :mark_migration_complete, [:version] => :environment do |_, args| + unless args[:version] + puts "Must specify a migration version as an argument".red + exit 1 + end + + version = args[:version].to_i + if version == 0 + puts "Version '#{args[:version]}' must be a non-zero integer".red + exit 1 + end + + sql = "INSERT INTO schema_migrations (version) VALUES (#{version})" + begin + ActiveRecord::Base.connection.execute(sql) + puts "Successfully marked '#{version}' as complete".green + rescue ActiveRecord::RecordNotUnique + puts "Migration version '#{version}' is already marked complete".yellow + end + end + + desc 'Drop all tables' + task :drop_tables => :environment do + connection = ActiveRecord::Base.connection + tables = connection.tables + tables.delete 'schema_migrations' + # Truncate schema_migrations to ensure migrations re-run + connection.execute('TRUNCATE schema_migrations') + tables.each { |t| connection.execute("DROP TABLE #{t}") } + end + end +end diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index 63bed2414df..320be9a0b61 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -3,9 +3,10 @@ require 'rake' describe 'gitlab:app namespace rake task' do before :all do - Rake.application.rake_require "tasks/gitlab/task_helpers" - Rake.application.rake_require "tasks/gitlab/backup" - Rake.application.rake_require "tasks/gitlab/shell" + Rake.application.rake_require 'tasks/gitlab/task_helpers' + Rake.application.rake_require 'tasks/gitlab/backup' + Rake.application.rake_require 'tasks/gitlab/shell' + Rake.application.rake_require 'tasks/gitlab/db' # empty task as env is already loaded Rake::Task.define_task :environment end @@ -37,6 +38,7 @@ describe 'gitlab:app namespace rake task' do allow(FileUtils).to receive(:mv).and_return(true) allow(Rake::Task["gitlab:shell:setup"]). to receive(:invoke).and_return(true) + ENV['force'] = 'yes' end let(:gitlab_version) { Gitlab::VERSION } @@ -52,13 +54,14 @@ describe 'gitlab:app namespace rake task' do it 'should invoke restoration on match' do allow(YAML).to receive(:load_file). and_return({ gitlab_version: gitlab_version }) - expect(Rake::Task["gitlab:backup:db:restore"]).to receive(:invoke) - expect(Rake::Task["gitlab:backup:repo:restore"]).to receive(:invoke) - expect(Rake::Task["gitlab:backup:builds:restore"]).to receive(:invoke) - expect(Rake::Task["gitlab:backup:uploads:restore"]).to receive(:invoke) - expect(Rake::Task["gitlab:backup:artifacts:restore"]).to receive(:invoke) - expect(Rake::Task["gitlab:backup:lfs:restore"]).to receive(:invoke) - expect(Rake::Task["gitlab:shell:setup"]).to receive(:invoke) + expect(Rake::Task['gitlab:db:drop_tables']).to receive(:invoke) + expect(Rake::Task['gitlab:backup:db:restore']).to receive(:invoke) + expect(Rake::Task['gitlab:backup:repo:restore']).to receive(:invoke) + expect(Rake::Task['gitlab:backup:builds:restore']).to receive(:invoke) + expect(Rake::Task['gitlab:backup:uploads:restore']).to receive(:invoke) + expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive(:invoke) + expect(Rake::Task['gitlab:backup:lfs:restore']).to receive(:invoke) + expect(Rake::Task['gitlab:shell:setup']).to receive(:invoke) expect { run_rake_task('gitlab:backup:restore') }.not_to raise_error end end @@ -177,17 +180,18 @@ describe 'gitlab:app namespace rake task' do end it 'does not invoke repositories restore' do - allow(Rake::Task["gitlab:shell:setup"]). + allow(Rake::Task['gitlab:shell:setup']). to receive(:invoke).and_return(true) allow($stdout).to receive :write - expect(Rake::Task["gitlab:backup:db:restore"]).to receive :invoke - expect(Rake::Task["gitlab:backup:repo:restore"]).not_to receive :invoke - expect(Rake::Task["gitlab:backup:uploads:restore"]).not_to receive :invoke - expect(Rake::Task["gitlab:backup:builds:restore"]).to receive :invoke - expect(Rake::Task["gitlab:backup:artifacts:restore"]).to receive :invoke - expect(Rake::Task["gitlab:backup:lfs:restore"]).to receive :invoke - expect(Rake::Task["gitlab:shell:setup"]).to receive :invoke + expect(Rake::Task['gitlab:db:drop_tables']).to receive :invoke + expect(Rake::Task['gitlab:backup:db:restore']).to receive :invoke + expect(Rake::Task['gitlab:backup:repo:restore']).not_to receive :invoke + expect(Rake::Task['gitlab:backup:uploads:restore']).not_to receive :invoke + expect(Rake::Task['gitlab:backup:builds:restore']).to receive :invoke + expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive :invoke + expect(Rake::Task['gitlab:backup:lfs:restore']).to receive :invoke + expect(Rake::Task['gitlab:shell:setup']).to receive :invoke expect { run_rake_task('gitlab:backup:restore') }.not_to raise_error end end |