diff options
26 files changed, 448 insertions, 122 deletions
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue index 396ecc3e291..df950e79690 100644 --- a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue +++ b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue @@ -163,7 +163,7 @@ export default { :ok-title="s__('SetStatusModal|Set status')" :cancel-title="s__('SetStatusModal|Remove status')" ok-variant="success" - class="set-user-status-modal" + modal-class="set-user-status-modal" @shown="setupEmojiListAndAutocomplete" @hide="hideEmojiMenu" @ok="setStatus" diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss index e36307f4f29..9028bfa8ec9 100644 --- a/app/assets/stylesheets/framework/typography.scss +++ b/app/assets/stylesheets/framework/typography.scss @@ -194,6 +194,141 @@ border-color: $gl-gray-200; } } + + &.grid-none { + > thead > tr { + > th { + border-bottom-width: 0; + border-right-width: 0; + border-left-width: 0; + + &:first-child { + border-left-width: 1px; + } + + &:last-child { + border-right-width: 1px; + } + } + } + + > tbody { + > tr > td { + border-width: 0; + + &:first-child { + border-left-width: 1px; + } + + &:last-child { + border-right-width: 1px; + } + } + + > tr:last-child > td { + border-bottom-width: 1px; + } + } + } + + + &.grid-rows { + > thead > tr > th, + > tbody > tr > td { + border-right-width: 0; + border-left-width: 0; + } + + > thead > tr { + > th:first-child { + border-left-width: 1px; + } + + > th:last-child { + border-right-width: 1px; + } + } + + > tbody > tr { + > td { + border-left-width: 0; + border-right-width: 0; + } + + > td:first-child { + border-left-width: 1px; + } + + > td:last-child { + border-right-width: 1px; + } + } + } + + &.grid-cols { + > thead > tr > th { + border-bottom-width: 0; + } + + > tbody > tr > td { + border-top-width: 0; + border-bottom-width: 0; + } + + > tbody > tr:last-child > td { + border-bottom-width: 1px; + } + } + + &.frame-sides { + > thead > tr > th { + border-top-width: 0; + } + + > tbody > tr:last-child > td { + border-bottom-width: 0; + } + } + + &.frame-topbot, + &.frame-ends { + > thead > tr > th:first-child, + > tbody > tr > td:first-child { + border-left-width: 0; + } + + > thead > tr > th:last-child, + > tbody > tr > td:last-child { + border-right-width: 0; + } + } + + &.frame-none { + > thead > tr > th { + border-top-width: 0; + } + + > tbody > tr:last-child > td { + border-bottom-width: 0; + } + + > thead > tr > th:first-child, + > tbody > tr > td:first-child { + border-left-width: 0; + } + + > thead > tr > th:last-child, + > tbody > tr > td:last-child { + border-right-width: 0; + } + } + + &.stripes-all tr, + &.stripes-odd tr:nth-of-type(odd), + &.stripes-even tr:nth-of-type(even), + &.stripes-hover tr:hover { + background: $gray-light; + } } table:dir(rtl) th { diff --git a/app/views/groups/_create_chat_team.html.haml b/app/views/groups/_create_chat_team.html.haml index 561e68a9155..2531993a095 100644 --- a/app/views/groups/_create_chat_team.html.haml +++ b/app/views/groups/_create_chat_team.html.haml @@ -8,7 +8,7 @@ .form-check.js-toggle-container .js-toggle-button.form-check-input= f.check_box(:create_chat_team, { checked: true }, true, false) = f.label :create_chat_team, class: 'form-check-label' do - Create a Mattermost team for this group + = _('Create a Mattermost team for this group') %br %small.light.js-toggle-content Mattermost URL: diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index 6d06bb246cb..0e78ce9f656 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -1,4 +1,4 @@ -- breadcrumb_title "General Settings" +- breadcrumb_title _("General Settings") - @content_class = "limit-container-width" unless fluid_layout - expanded = expanded_by_default? @@ -32,7 +32,7 @@ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only{ role: 'button' } = s_('GroupSettings|Badges') %button.btn.js-settings-toggle{ type: 'button' } - = expanded ? 'Collapse' : 'Expand' + = expanded ? _('Collapse') : _('Expand') %p = s_('GroupSettings|Customize your group badges.') = link_to s_('GroupSettings|Learn more about badges.'), help_page_path('user/project/badges') diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml index 06e05d898d6..376624f4786 100644 --- a/app/views/groups/new.html.haml +++ b/app/views/groups/new.html.haml @@ -40,5 +40,5 @@ = render 'create_chat_team', f: f if Gitlab.config.mattermost.enabled .form-actions - = f.submit 'Create group', class: "btn btn-success" - = link_to 'Cancel', dashboard_groups_path, class: 'btn btn-cancel' + = f.submit _('Create group'), class: "btn btn-success" + = link_to _('Cancel'), dashboard_groups_path, class: 'btn btn-cancel' diff --git a/app/views/groups/settings/_advanced.html.haml b/app/views/groups/settings/_advanced.html.haml index 64fec260f3b..307309c6ca3 100644 --- a/app/views/groups/settings/_advanced.html.haml +++ b/app/views/groups/settings/_advanced.html.haml @@ -1,12 +1,12 @@ .sub-section - %h4.warning-title Change group path + %h4.warning-title= s_('GroupSettings|Change group path') = form_for @group, html: { multipart: true, class: 'gl-show-field-errors' }, authenticity_token: true do |f| = form_errors(@group) .form-group %p - Changing group path can have unintended side effects. + = s_('GroupSettings|Changing group path can have unintended side effects.') = succeed '.' do - = link_to 'Learn more', help_page_path('user/group/index', anchor: 'changing-a-groups-path'), target: '_blank' + = link_to _('Learn more'), help_page_path('user/group/index', anchor: 'changing-a-groups-path'), target: '_blank' .input-group.gl-field-error-anchor .group-root-path.input-group-prepend.has-tooltip{ title: group_path(@group), :'data-placement' => 'bottom' } @@ -18,24 +18,26 @@ = f.text_field :path, placeholder: 'open-source', class: 'form-control', autofocus: local_assigns[:autofocus] || false, required: true, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, - title: 'Please choose a group path with no special characters.', + title: s_('GroupSettings|Please choose a group path with no special characters.'), "data-bind-in" => "#{'create_chat_team' if Gitlab.config.mattermost.enabled}" - = f.submit 'Change group path', class: 'btn btn-warning' + = f.submit s_('GroupSettings|Change group path'), class: 'btn btn-warning' .sub-section - %h4.warning-title Transfer group + %h4.warning-title= s_('GroupSettings|Transfer group') = form_for @group, url: transfer_group_path(@group), method: :put, html: { class: 'js-group-transfer-form' } do |f| .form-group = dropdown_tag('Select parent group', options: { toggle_class: 'js-groups-dropdown', title: 'Parent Group', filter: true, dropdown_class: 'dropdown-open-top dropdown-group-transfer', placeholder: 'Search groups', data: { data: parent_group_options(@group) } }) = hidden_field_tag 'new_parent_group_id' %ul - %li Be careful. Changing a group's parent can have unintended #{link_to 'side effects', 'https://docs.gitlab.com/ce/user/project/index.html#redirects-when-changing-repository-paths', target: 'blank'}. - %li You can only transfer the group to a group you manage. - %li You will need to update your local repositories to point to the new location. - %li If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility. - = f.submit 'Transfer group', class: 'btn btn-warning' + - side_effects_link_start = '<a href="https://docs.gitlab.com/ce/user/project/index.html#redirects-when-changing-repository-paths" target="_blank">' + - warning_text = s_("GroupSettings|Be careful. Changing a group's parent can have unintended %{side_effects_link_start}side effects%{side_effects_link_end}.") % { side_effects_link_start: side_effects_link_start, side_effects_link_end:'</a>' } + %li= warning_text.html_safe + %li= s_('GroupSettings|You can only transfer the group to a group you manage.') + %li= s_('GroupSettings|You will need to update your local repositories to point to the new location.') + %li= s_("GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility.") + = f.submit s_('GroupSettings|Transfer group'), class: 'btn btn-warning' .sub-section %h4.danger-title= _('Remove group') diff --git a/app/views/shared/_confirm_modal.html.haml b/app/views/shared/_confirm_modal.html.haml index 8e3b482e27d..ecb462205b0 100644 --- a/app/views/shared/_confirm_modal.html.haml +++ b/app/views/shared/_confirm_modal.html.haml @@ -12,9 +12,8 @@ %p %span.js-warning-text= _('This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention.') %br - Please type - %code.js-confirm-danger-match= phrase - to proceed or close this modal to cancel. + - phrase_code = '<code class="js-confirm-danger-match">%{phrase_name}</code>'.html_safe % { phrase_name: phrase } + = _('Please type %{phrase_code} to proceed or close this modal to cancel.').html_safe % { phrase_code: phrase_code } .form-group = text_field_tag 'confirm_name_input', '', class: 'form-control js-confirm-danger-input qa-confirm-input' diff --git a/app/views/shared/_group_form.html.haml b/app/views/shared/_group_form.html.haml index 973c756f496..959792718ca 100644 --- a/app/views/shared/_group_form.html.haml +++ b/app/views/shared/_group_form.html.haml @@ -30,9 +30,9 @@ - if @group.persisted? .alert.alert-warning.prepend-top-10 - Changing group path can have unintended side effects. + = _('Changing group path can have unintended side effects.') = succeed '.' do - = link_to 'Learn more', help_page_path('user/group/index', anchor: 'changing-a-groups-path'), target: '_blank' + = link_to _('Learn more'), help_page_path('user/group/index', anchor: 'changing-a-groups-path'), target: '_blank' - if @group.persisted? .row diff --git a/changelogs/unreleased/30839-asciidoc-table-styles.yml b/changelogs/unreleased/30839-asciidoc-table-styles.yml new file mode 100644 index 00000000000..11960f3620d --- /dev/null +++ b/changelogs/unreleased/30839-asciidoc-table-styles.yml @@ -0,0 +1,5 @@ +--- +title: Enable grid, frame and stripes styling on AsciiDoc tables +merge_request: 18165 +author: Guillaume Grossetie +type: fixed diff --git a/changelogs/unreleased/fix-set-status-emoji-button.yml b/changelogs/unreleased/fix-set-status-emoji-button.yml new file mode 100644 index 00000000000..e7a8c119c91 --- /dev/null +++ b/changelogs/unreleased/fix-set-status-emoji-button.yml @@ -0,0 +1,5 @@ +--- +title: Fix styling of set status emoji picker +merge_request: 18509 +author: +type: fixed diff --git a/db/post_migrate/20191004134055_drop_unused_analytics_repository_file_edits.rb b/db/post_migrate/20191004134055_drop_unused_analytics_repository_file_edits.rb deleted file mode 100644 index 7bf92080fe6..00000000000 --- a/db/post_migrate/20191004134055_drop_unused_analytics_repository_file_edits.rb +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -class DropUnusedAnalyticsRepositoryFileEdits < ActiveRecord::Migration[5.2] - DOWNTIME = false - - def up - # The table was never used, there is no app code that writes or reads the table. Safe to remove. - drop_table :analytics_repository_file_edits - end - - def down - create_table :analytics_repository_file_edits do |t| - t.references :project, - index: true, - foreign_key: { on_delete: :cascade }, null: false - t.references :analytics_repository_file, - index: false, - foreign_key: { on_delete: :cascade }, - null: false - t.date :committed_date, - null: false - t.integer :num_edits, - null: false, - default: 0 - end - - add_index :analytics_repository_file_edits, - [:analytics_repository_file_id, :committed_date, :project_id], - name: 'index_file_edits_on_committed_date_file_id_and_project_id', - unique: true - end -end diff --git a/db/schema.rb b/db/schema.rb index 1b1a6773c14..b9952cfc12d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2019_10_04_134055) do +ActiveRecord::Schema.define(version: 2019_10_04_133612) do # These are extensions that must be enabled in order to support this database enable_extension "pg_trgm" @@ -102,6 +102,15 @@ ActiveRecord::Schema.define(version: 2019_10_04_134055) do t.index ["project_id", "committed_date", "analytics_repository_file_id"], name: "index_file_commits_on_committed_date_file_id_and_project_id", unique: true end + create_table "analytics_repository_file_edits", force: :cascade do |t| + t.bigint "project_id", null: false + t.bigint "analytics_repository_file_id", null: false + t.date "committed_date", null: false + t.integer "num_edits", default: 0, null: false + t.index ["analytics_repository_file_id", "committed_date", "project_id"], name: "index_file_edits_on_committed_date_file_id_and_project_id", unique: true + t.index ["project_id"], name: "index_analytics_repository_file_edits_on_project_id" + end + create_table "analytics_repository_files", force: :cascade do |t| t.bigint "project_id", null: false t.string "file_path", limit: 4096, null: false @@ -3900,6 +3909,8 @@ ActiveRecord::Schema.define(version: 2019_10_04_134055) do add_foreign_key "analytics_language_trend_repository_languages", "projects", on_delete: :cascade add_foreign_key "analytics_repository_file_commits", "analytics_repository_files", on_delete: :cascade add_foreign_key "analytics_repository_file_commits", "projects", on_delete: :cascade + add_foreign_key "analytics_repository_file_edits", "analytics_repository_files", on_delete: :cascade + add_foreign_key "analytics_repository_file_edits", "projects", on_delete: :cascade add_foreign_key "analytics_repository_files", "projects", on_delete: :cascade add_foreign_key "application_settings", "namespaces", column: "custom_project_templates_group_id", on_delete: :nullify add_foreign_key "application_settings", "projects", column: "file_template_project_id", name: "fk_ec757bd087", on_delete: :nullify diff --git a/doc/administration/index.md b/doc/administration/index.md index f79719e1d3e..fb6c1af991b 100644 --- a/doc/administration/index.md +++ b/doc/administration/index.md @@ -212,6 +212,7 @@ who are aware of the risks. - [Useful diagnostics tools](troubleshooting/diagnostics_tools.md) - [Useful Linux commands](troubleshooting/linux_cheat_sheet.md) - [Troubleshooting Kubernetes](troubleshooting/kubernetes_cheat_sheet.md) +- [Troubleshooting PostgreSQL](troubleshooting/postgresql.md) - [Guide to test environments](troubleshooting/test_environments.md) (for Support Engineers) - [GitLab Rails console commands](troubleshooting/gitlab_rails_cheat_sheet.md) (for Support Engineers) - Useful links: diff --git a/doc/administration/troubleshooting/postgresql.md b/doc/administration/troubleshooting/postgresql.md new file mode 100644 index 00000000000..3bbc3f23d83 --- /dev/null +++ b/doc/administration/troubleshooting/postgresql.md @@ -0,0 +1,146 @@ +--- +type: reference +--- + +# PostgreSQL + +This page is useful information about PostgreSQL that the GitLab Support +Team sometimes uses while troubleshooting. GitLab is making this public, so that anyone +can make use of the Support team's collected knowledge. + +CAUTION: **Caution:** Some procedures documented here may break your GitLab instance. Use at your own risk. + +If you are on a [paid tier](https://about.gitlab.com/pricing/) and are not sure how +to use these commands, it is best to [contact Support](https://about.gitlab.com/support/) +and they will assist you with any issues you are having. + +## Other GitLab PostgreSQL documentation + +This section is for links to information elsewhere in the GitLab documentation. + +### Procedures + +- [Connect to the PostgreSQL console.](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database) + +- [Omnibus database procedures](https://docs.gitlab.com/omnibus/settings/database.html) including + - SSL: enabling, disabling, and verifying. + - Enabling Write Ahead Log (WAL) archiving. + - Using an external (non-Omnibus) PostgreSQL installation; and backing it up. + - Listening on TCP/IP as well as or instead of sockets. + - Storing data in another location. + - Destructively reseeding the GitLab database. + - Guidance around updating packaged PostgreSQL, including how to stop it happening automatically. + +- [More about external PostgreSQL](/ee/administration/external_database.html) + +- [Running GEO with external PostgreSQL](/ee/administration/geo/replication/external_database.html) + +- [Upgrades when running PostgreSQL configured for HA.](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-gitlab-ha-cluster) + +- Consuming PostgreSQL from [within CI runners](/ee/ci/services/postgres.html) + +- [Using Slony to update PostgreSQL](/ee/update/upgrading_postgresql_using_slony.html) + - Uses replication to handle PostgreSQL upgrades - providing the schemas are the same. + - Reduces downtime to a short window for swinging over to the newer vewrsion. + +- Managing Omnibus PostgreSQL versions [from the development docs](https://docs.gitlab.com/omnibus/development/managing-postgresql-versions.html) + +- [PostgreSQL scaling and HA](/ee/administration/high_availability/database.html) + - including [troubleshooting](/ee/administration/high_availability/database.html#troubleshooting) gitlab-ctl repmgr-check-master and pgbouncer errors + +- [Developer database documentation](/ee/development/README.html#database-guides) - some of which is absolutely not for production use. Including: + - understanding EXPLAIN plans + +### Troubleshooting/Fixes + +- [GitLab database requirements](/ee/install/requirements.html#database) including + - Support for MySQL was removed in GitLab 12.1; [migrate to PostgreSQL](/ee/update/mysql_to_postgresql.html) + - required extension pg_trgm + - required extension postgres_fdw for Geo + +- Errors like this in the production/sidekiq log; see: [Set default_transaction_isolation into read committed](https://docs.gitlab.com/omnibus/settings/database.html#set-default_transaction_isolation-into-read-committed) + +``` +ActiveRecord::StatementInvalid PG::TRSerializationFailure: ERROR: could not serialize access due to concurrent update +``` + +- PostgreSQL HA - [replication slot errors](https://docs.gitlab.com/omnibus/settings/database.html#troubleshooting-upgrades-in-an-ha-cluster) + +``` +pg_basebackup: could not create temporary replication slot "pg_basebackup_12345": ERROR: all replication slots are in use +HINT: Free one or increase max_replication_slots. +``` + +- GEO [replication errors](/ee/administration/geo/replication/troubleshooting.html#fixing-replication-errors) including: + +``` +ERROR: replication slots can only be used if max_replication_slots > 0 + +FATAL: could not start WAL streaming: ERROR: replication slot “geo_secondary_my_domain_com” does not exist + +Command exceeded allowed execution time + +PANIC: could not write to file ‘pg_xlog/xlogtemp.123’: No space left on device +``` + +- [Checking GEO configuration](/ee/administration/geo/replication/troubleshooting.html#checking-configuration) including + - reconfiguring hosts/ports + - checking and fixing user/password mappings + +- [Common GEO errors](/ee/administration/geo/replication/troubleshooting.html#fixing-common-errors) + +## Support topics + +### Database deadlocks + +References: + +- [Issue #1 Deadlocks with GitLab 12.1, PostgreSQL 10.7](https://gitlab.com/gitlab-org/gitlab/issues/30528) +- [Customer ticket (internal) GitLab 12.1.6](https://gitlab.zendesk.com/agent/tickets/134307) and [google doc (internal)](https://docs.google.com/document/d/19xw2d_D1ChLiU-MO1QzWab-4-QXgsIUcN5e_04WTKy4) +- [Issue #2 deadlocks can occur if an instance is flooded with pushes](https://gitlab.com/gitlab-org/gitlab/issues/33650). Provided for context about how GitLab code can have this sort of unanticipated effect in unusual situations. + +``` +ERROR: deadlock detected +``` + +Three applicable timeouts are identified in the issue [#1](https://gitlab.com/gitlab-org/gitlab/issues/30528); our recommended settings are as follows: + +``` +deadlock_timeout = 5s +statement_timeout = 15s +idle_in_transaction_session_timeout = 60s +``` + +Quoting from from issue [#1](https://gitlab.com/gitlab-org/gitlab/issues/30528): + +> "If a deadlock is hit, and we resolve it through aborting the transaction after a short period, then the retry mechanisms we already have will make the deadlocked piece of work try again, and it's unlikely we'll deadlock multiple times in a row." + +TIP: **Tip:** In support, our general approach to reconfiguring timeouts (applies also to the HTTP stack as well) is that it's acceptable to do it temporarily as a workaround. If it makes GitLab usable for the customer, then it buys time to understand the problem more completely, implement a hot fix, or make some other change that addresses the root cause. Generally, the timeouts should be put back to reasonable defaults once the root cause is resolved. + +In this case, the guidance we had from development was to drop deadlock_timeout and/or statement_timeout but to leave the third setting at 60s. Setting idle_in_transaction protects the database from sessions potentially hanging for days. There's more discussion in [the issue relating to introducing this timeout on gitlab.com.](https://gitlab.com/gitlab-com/gl-infra/production/issues/1053) + +PostgresSQL defaults: + +- statement_timeout = 0 (never) +- idle_in_transaction_session_timeout = 0 (never) + +Comments in issue [#1](https://gitlab.com/gitlab-org/gitlab/issues/30528) indicate that these should both be set to at least a number of minutes for all Omnibus installations (so they don't hang indefinitely). However, 15s for statement_timeout is very short, and will only be effective if the underlying infrastructure is very performant. + +See current settings with: + +``` +sudo gitlab-rails runner "c = ApplicationRecord.connection ; puts c.execute('SHOW statement_timeout').to_a ; +puts c.execute('SHOW lock_timeout').to_a ; +puts c.execute('SHOW idle_in_transaction_session_timeout').to_a ;" +``` + +It may take a little while to respond. + +``` +{"statement_timeout"=>"1min"} +{"lock_timeout"=>"0"} +{"idle_in_transaction_session_timeout"=>"1min"} +``` + +NOTE: **Note:** +These are Omnibus settings. If an external database, such as a customer's PostgreSQL installation or Amazon RDS is being used, these values don't get set, and would have to be set externally. diff --git a/doc/development/documentation/site_architecture/index.md b/doc/development/documentation/site_architecture/index.md index f8d63a54053..f5a12e9c216 100644 --- a/doc/development/documentation/site_architecture/index.md +++ b/doc/development/documentation/site_architecture/index.md @@ -68,7 +68,7 @@ the GitLab Documentation website. ## Global navigation -Read through the global navigation](global_nav.md) documentation to understand: +Read through [the global navigation documentation](global_nav.md) to understand: - How the global navigation is built. - How to add new navigation items. diff --git a/doc/development/gotchas.md b/doc/development/gotchas.md index 5557a113d05..c7eed880554 100644 --- a/doc/development/gotchas.md +++ b/doc/development/gotchas.md @@ -114,6 +114,7 @@ Instead of writing: # Don't do this: expect_any_instance_of(Project).to receive(:add_import_job) +# Don't do this: allow_any_instance_of(Project).to receive(:add_import_job) ``` @@ -125,12 +126,13 @@ expect_next_instance_of(Project) do |project| expect(project).to receive(:add_import_job) end +# Do this: allow_next_instance_of(Project) do |project| allow(project).to receive(:add_import_job) end ``` -If we also want to initialized the instance with some particular arguments, we +If we also want to initialize the instance with some particular arguments, we could also pass it like: ```ruby diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb index c87466de357..974e32ce17c 100644 --- a/lib/backup/repository.rb +++ b/lib/backup/repository.rb @@ -41,12 +41,6 @@ module Backup end end - def prepare_directories - Gitlab.config.repositories.storages.each do |name, _repository_storage| - Gitlab::GitalyClient::StorageService.new(name).delete_all_repositories - end - end - def backup_project(project) path_to_project_bundle = path_to_bundle(project) Gitlab::GitalyClient::RepositoryService.new(project.repository) @@ -75,13 +69,13 @@ module Backup end def restore - prepare_directories - Project.find_each(batch_size: 1000) do |project| progress.print " * #{project.full_path} ... " path_to_project_bundle = path_to_bundle(project) + project.repository.remove rescue nil restore_repo_success = nil + if File.exist?(path_to_project_bundle) begin project.repository.create_from_bundle(path_to_project_bundle) diff --git a/lib/banzai/filter/ascii_doc_sanitization_filter.rb b/lib/banzai/filter/ascii_doc_sanitization_filter.rb index 9105e86ad04..e41f7d8488a 100644 --- a/lib/banzai/filter/ascii_doc_sanitization_filter.rb +++ b/lib/banzai/filter/ascii_doc_sanitization_filter.rb @@ -22,6 +22,10 @@ module Banzai CHECKLIST_CLASSES = %w(fa fa-check-square-o fa-square-o).freeze LIST_CLASSES = %w(checklist none no-bullet unnumbered unstyled).freeze + TABLE_FRAME_CLASSES = %w(frame-all frame-topbot frame-sides frame-ends frame-none).freeze + TABLE_GRID_CLASSES = %w(grid-all grid-rows grid-cols grid-none).freeze + TABLE_STRIPES_CLASSES = %w(stripes-all stripes-odd stripes-even stripes-hover stripes-none).freeze + ELEMENT_CLASSES_WHITELIST = { span: %w(big small underline overline line-through).freeze, div: ['admonitionblock'].freeze, @@ -29,7 +33,8 @@ module Banzai i: ADMONITION_CLASSES + CALLOUT_CLASSES + CHECKLIST_CLASSES, ul: LIST_CLASSES, ol: LIST_CLASSES, - a: ['anchor'].freeze + a: ['anchor'].freeze, + table: TABLE_FRAME_CLASSES + TABLE_GRID_CLASSES + TABLE_STRIPES_CLASSES }.freeze def customize_whitelist(whitelist) @@ -45,6 +50,7 @@ module Banzai whitelist[:attributes]['ul'] = %w(class) whitelist[:attributes]['ol'] = %w(class) whitelist[:attributes]['a'].push('class') + whitelist[:attributes]['table'] = %w(class) whitelist[:transformers].push(self.class.remove_element_classes) # Allow `id` in heading elements for section anchors diff --git a/lib/gitlab/gitaly_client/storage_service.rb b/lib/gitlab/gitaly_client/storage_service.rb index c7fcef6ddc5..e69de29bb2d 100644 --- a/lib/gitlab/gitaly_client/storage_service.rb +++ b/lib/gitlab/gitaly_client/storage_service.rb @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module GitalyClient - class StorageService - def initialize(storage) - @storage = storage - end - - # Delete all repositories in the storage. This is a slow and VERY DESTRUCTIVE operation. - def delete_all_repositories - request = Gitaly::DeleteAllRepositoriesRequest.new(storage_name: @storage) - GitalyClient.call(@storage, :storage_service, :delete_all_repositories, request, timeout: GitalyClient.long_timeout) - end - end - end -end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index b5ffe1bc28a..3b3eb4d649e 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2946,6 +2946,9 @@ msgstr "" msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}." msgstr "" +msgid "Changing group path can have unintended side effects." +msgstr "" + msgid "Charts" msgstr "" @@ -4618,6 +4621,9 @@ msgstr "" msgid "Create a GitLab account first, and then connect it to your %{label} account." msgstr "" +msgid "Create a Mattermost team for this group" +msgstr "" + msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies." msgstr "" @@ -8249,6 +8255,15 @@ msgstr "" msgid "GroupSettings|Badges" msgstr "" +msgid "GroupSettings|Be careful. Changing a group's parent can have unintended %{side_effects_link_start}side effects%{side_effects_link_end}." +msgstr "" + +msgid "GroupSettings|Change group path" +msgstr "" + +msgid "GroupSettings|Changing group path can have unintended side effects." +msgstr "" + msgid "GroupSettings|Custom project templates" msgstr "" @@ -8261,6 +8276,9 @@ msgstr "" msgid "GroupSettings|Disable email notifications" msgstr "" +msgid "GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility." +msgstr "" + msgid "GroupSettings|Learn more about badges." msgstr "" @@ -8273,6 +8291,9 @@ msgstr "" msgid "GroupSettings|Pipeline settings was updated for the group" msgstr "" +msgid "GroupSettings|Please choose a group path with no special characters." +msgstr "" + msgid "GroupSettings|Prevent sharing a project within %{group} with other groups" msgstr "" @@ -8303,6 +8324,15 @@ msgstr "" msgid "GroupSettings|This setting will override user notification preferences for all members of the group, subgroups, and projects." msgstr "" +msgid "GroupSettings|Transfer group" +msgstr "" + +msgid "GroupSettings|You can only transfer the group to a group you manage." +msgstr "" + +msgid "GroupSettings|You will need to update your local repositories to point to the new location." +msgstr "" + msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group" msgstr "" @@ -11906,6 +11936,9 @@ msgstr "" msgid "Please try again" msgstr "" +msgid "Please type %{phrase_code} to proceed or close this modal to cancel." +msgstr "" + msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version." msgstr "" diff --git a/qa/qa/page/group/new.rb b/qa/qa/page/group/new.rb index 9e37d14fbf3..e01b8754d55 100644 --- a/qa/qa/page/group/new.rb +++ b/qa/qa/page/group/new.rb @@ -11,7 +11,7 @@ module QA end view 'app/views/groups/new.html.haml' do - element :create_group_button, "submit 'Create group'" # rubocop:disable QA/ElementWithPattern + element :create_group_button, "submit _('Create group')" # rubocop:disable QA/ElementWithPattern element :visibility_radios, 'visibility_level:' # rubocop:disable QA/ElementWithPattern end diff --git a/spec/finders/todos_finder_spec.rb b/spec/finders/todos_finder_spec.rb index a0bf48f218a..9a3ffffb3f2 100644 --- a/spec/finders/todos_finder_spec.rb +++ b/spec/finders/todos_finder_spec.rb @@ -73,6 +73,28 @@ describe TodosFinder do end end + context 'when filtering by author' do + let(:author1) { create(:user) } + let(:author2) { create(:user) } + + let!(:todo1) { create(:todo, user: user, author: author1) } + let!(:todo2) { create(:todo, user: user, author: author2) } + + it 'returns correct todos when filtering by an author' do + todos = finder.new(user, { author_id: author1.id }).execute + + expect(todos).to match_array([todo1]) + end + + context 'querying for multiple authors' do + it 'returns the correct todo items' do + todos = finder.new(user, { author_id: [author2.id, author1.id] }).execute + + expect(todos).to match_array([todo2, todo1]) + end + end + end + context 'with subgroups' do let(:subgroup) { create(:group, parent: group) } let!(:todo3) { create(:todo, user: user, group: subgroup, target: issue) } diff --git a/spec/lib/backup/repository_spec.rb b/spec/lib/backup/repository_spec.rb index 582effcc303..bf827fb3914 100644 --- a/spec/lib/backup/repository_spec.rb +++ b/spec/lib/backup/repository_spec.rb @@ -83,30 +83,6 @@ describe Backup::Repository do end end - describe '#prepare_directories', :seed_helper do - before do - allow(FileUtils).to receive(:mkdir_p).and_call_original - allow(FileUtils).to receive(:mv).and_call_original - end - - after(:all) do - ensure_seeds - end - - it' removes all repositories' do - # Sanity check: there should be something for us to delete - expect(list_repositories).to include(File.join(SEED_STORAGE_PATH, TEST_REPO_PATH)) - - subject.prepare_directories - - expect(list_repositories).to be_empty - end - - def list_repositories - Dir[File.join(SEED_STORAGE_PATH, '*.git')] - end - end - describe '#empty_repo?' do context 'for a wiki' do let(:wiki) { create(:project_wiki) } diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index 354260f23f6..04a648a0da0 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -2254,7 +2254,7 @@ describe Gitlab::Git::Repository, :seed_helper do end describe '#remove' do - let(:project) { create(:project, :repository)} + let(:project) { create(:project, :repository) } let(:repository) { project.repository } it 'removes the repository' do @@ -2264,5 +2264,17 @@ describe Gitlab::Git::Repository, :seed_helper do expect(repository.raw_repository.exists?).to be false end + + context 'when the repository does not exist' do + let(:repository) { create(:project).repository } + + it 'is idempotent' do + expect(repository.exists?).to be false + + repository.remove + + expect(repository.raw_repository.exists?).to be false + end + end end end diff --git a/spec/lib/gitlab/gitaly_client/storage_service_spec.rb b/spec/lib/gitlab/gitaly_client/storage_service_spec.rb deleted file mode 100644 index 6c25e2d6ebd..00000000000 --- a/spec/lib/gitlab/gitaly_client/storage_service_spec.rb +++ /dev/null @@ -1,13 +0,0 @@ -require 'spec_helper' - -describe Gitlab::GitalyClient::StorageService do - describe '#delete_all_repositories' do - let!(:project) { create(:project, :repository) } - - it 'removes all repositories' do - described_class.new(project.repository_storage).delete_all_repositories - - expect(project.repository.exists?).to be(false) - end - end -end diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index b307453f078..e58919c8688 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -117,6 +117,45 @@ describe 'gitlab:app namespace rake task' do expect(raw_repo.empty?).to be(true) end end + + context 'when the backup is restored' do + let!(:included_project) { create(:project, :repository) } + + before do + expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout + + backup_tar = Dir.glob(File.join(Gitlab.config.backup.path, '*_gitlab_backup.tar')).last + allow(Dir).to receive(:glob).and_return([backup_tar]) + allow(File).to receive(:exist?).and_return(true) + allow(Kernel).to receive(:system).and_return(true) + allow(FileUtils).to receive(:cp_r).and_return(true) + allow(FileUtils).to receive(:mv).and_return(true) + allow(YAML).to receive(:load_file) + .and_return({ gitlab_version: Gitlab::VERSION }) + + 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:pages:restore']).to receive(:invoke) + expect(Rake::Task['gitlab:backup:lfs:restore']).to receive(:invoke) + expect(Rake::Task['gitlab:backup:registry:restore']).to receive(:invoke) + expect(Rake::Task['gitlab:shell:setup']).to receive(:invoke) + + # We only need a backup of the repositories for this test + stub_env('SKIP', 'db,uploads,builds,artifacts,lfs,registry') + end + + it 'restores the data' do + expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout + + raw_repo = included_project.repository.raw + + expect(raw_repo.empty?).to be(false) + end + end end # backup_restore task describe 'backup' do |