diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-16 15:08:41 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-16 15:08:41 +0000 |
commit | d47f9d2304dbc3a23bba7fe7a5cd07218eeb41cd (patch) | |
tree | 4b4efa1ccd8246fba2dc9f8816d9d2c0268e9818 | |
parent | c158fa8d69c704663d289341a014c44c062cda88 (diff) | |
download | gitlab-ce-d47f9d2304dbc3a23bba7fe7a5cd07218eeb41cd.tar.gz |
Add latest changes from gitlab-org/gitlab@master
44 files changed, 368 insertions, 297 deletions
diff --git a/app/finders/group_members_finder.rb b/app/finders/group_members_finder.rb index 05151b4f1f3..ffa1552627a 100644 --- a/app/finders/group_members_finder.rb +++ b/app/finders/group_members_finder.rb @@ -36,6 +36,8 @@ class GroupMembersFinder < UnionFinder relations << descendant_members end + return GroupMember.none if relations.empty? + members = find_union(relations, GroupMember) filter_members(members, params) end diff --git a/app/models/epic.rb b/app/models/epic.rb index 8222bbf9656..1203c6c1fc3 100644 --- a/app/models/epic.rb +++ b/app/models/epic.rb @@ -5,7 +5,7 @@ class Epic < ApplicationRecord include IgnorableColumns - ignore_column :milestone_id, remove_after: '2019-12-15', remove_with: '12.7' + ignore_column :milestone_id, remove_after: '2020-02-01', remove_with: '12.8' def self.link_reference_pattern nil diff --git a/app/models/project.rb b/app/models/project.rb index c7c2a9e34fb..735c9ebda7f 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1325,7 +1325,7 @@ class Project < ApplicationRecord end def has_active_hooks?(hooks_scope = :push_hooks) - hooks.hooks_for(hooks_scope).any? || SystemHook.hooks_for(hooks_scope).any? || Gitlab::Plugin.any? + hooks.hooks_for(hooks_scope).any? || SystemHook.hooks_for(hooks_scope).any? || Gitlab::FileHook.any? end def has_active_services?(hooks_scope = :push_hooks) diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 92746d28f05..b3b3de21dee 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -14,8 +14,12 @@ class Snippet < ApplicationRecord include Editable include Gitlab::SQL::Pattern include FromUnion + include IgnorableColumns + extend ::Gitlab::Utils::Override + ignore_column :storage_version, remove_with: '12.9', remove_after: '2020-03-22' + cache_markdown_field :title, pipeline: :single_line cache_markdown_field :description cache_markdown_field :content diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb index 06d2037fb63..0d369c23b57 100644 --- a/app/services/system_hooks_service.rb +++ b/app/services/system_hooks_service.rb @@ -14,7 +14,7 @@ class SystemHooksService hook.async_execute(data, 'system_hooks') end - Gitlab::Plugin.execute_all_async(data) + Gitlab::FileHook.execute_all_async(data) end private diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml index eed3ec74d60..1c14291b58e 100644 --- a/app/views/admin/hooks/index.html.haml +++ b/app/views/admin/hooks/index.html.haml @@ -11,4 +11,4 @@ = render 'shared/web_hooks/index', hooks: @hooks, hook_class: @hook.class -= render 'shared/plugins/index' += render 'shared/file_hooks/index' diff --git a/app/views/shared/file_hooks/_index.html.haml b/app/views/shared/file_hooks/_index.html.haml new file mode 100644 index 00000000000..74eb6c94116 --- /dev/null +++ b/app/views/shared/file_hooks/_index.html.haml @@ -0,0 +1,24 @@ +- file_hooks = Gitlab::FileHook.files + +.row.prepend-top-default + .col-lg-4 + %h4.prepend-top-0 + = _('File Hooks') + %p + = _('File hooks are similar to system hooks but are executed as files instead of sending data to a URL.') + = link_to _('For more information, see the File Hooks documentation.'), help_page_path('administration/file_hooks') + + + .col-lg-8.append-bottom-default + - if file_hooks.any? + .card + .card-header + = _('File Hooks (%{count})') % { count: file_hooks.count } + %ul.content-list + - file_hooks.each do |file| + %li + .monospace + = File.basename(file) + - else + .card.bg-light.text-center + .nothing-here-block= _('No file hooks found.') diff --git a/app/views/shared/plugins/_index.html.haml b/app/views/shared/plugins/_index.html.haml deleted file mode 100644 index 9d230d12be2..00000000000 --- a/app/views/shared/plugins/_index.html.haml +++ /dev/null @@ -1,23 +0,0 @@ -- plugins = Gitlab::Plugin.files - -.row.prepend-top-default - .col-lg-4 - %h4.prepend-top-0 - Plugins - %p - #{link_to 'Plugins', help_page_path('administration/plugins')} are similar to - system hooks but are executed as files instead of sending data to a URL. - - .col-lg-8.append-bottom-default - - if plugins.any? - .card - .card-header - Plugins (#{plugins.count}) - %ul.content-list - - plugins.each do |file| - %li - .monospace - = File.basename(file) - - else - .card.bg-light.text-center - .nothing-here-block No plugins found. diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index 330e9fafa69..62b37f52cce 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -158,7 +158,7 @@ - pages - pages_domain_verification - pages_domain_ssl_renewal -- plugin +- file_hook - post_receive - process_commit - project_cache diff --git a/app/workers/plugin_worker.rb b/app/workers/file_hook_worker.rb index e708031abdf..24fc2d75d24 100644 --- a/app/workers/plugin_worker.rb +++ b/app/workers/file_hook_worker.rb @@ -1,16 +1,16 @@ # frozen_string_literal: true -class PluginWorker +class FileHookWorker include ApplicationWorker sidekiq_options retry: false feature_category :integrations def perform(file_name, data) - success, message = Gitlab::Plugin.execute(file_name, data) + success, message = Gitlab::FileHook.execute(file_name, data) unless success - Gitlab::PluginLogger.error("Plugin Error => #{file_name}: #{message}") + Gitlab::FileHookLogger.error("File Hook Error => #{file_name}: #{message}") end true diff --git a/changelogs/unreleased/118604-design-view-left-right-keyboard-arrows-through-designs.yml b/changelogs/unreleased/118604-design-view-left-right-keyboard-arrows-through-designs.yml new file mode 100644 index 00000000000..70c2e1e5308 --- /dev/null +++ b/changelogs/unreleased/118604-design-view-left-right-keyboard-arrows-through-designs.yml @@ -0,0 +1,5 @@ +--- +title: 'Resolve Design View: Left/Right keyboard arrows through Designs' +merge_request: 22870 +author: +type: added diff --git a/changelogs/unreleased/197143-nomethoderror-undefined-method-sort_by_attribute-for-nil-nilclass.yml b/changelogs/unreleased/197143-nomethoderror-undefined-method-sort_by_attribute-for-nil-nilclass.yml new file mode 100644 index 00000000000..843e611b06c --- /dev/null +++ b/changelogs/unreleased/197143-nomethoderror-undefined-method-sort_by_attribute-for-nil-nilclass.yml @@ -0,0 +1,6 @@ +--- +title: Add returning relation from GroupMembersFinder if called on root group with + only inherited param +merge_request: 23161 +author: +type: fixed diff --git a/changelogs/unreleased/22776-update-project-regex.yml b/changelogs/unreleased/22776-update-project-regex.yml new file mode 100644 index 00000000000..0866e308418 --- /dev/null +++ b/changelogs/unreleased/22776-update-project-regex.yml @@ -0,0 +1,5 @@ +--- +title: Allow Unicode 11 emojis in project names +merge_request: 22776 +author: Harm Berntsen +type: changed diff --git a/changelogs/unreleased/33892-add-conan-install-instructions.yml b/changelogs/unreleased/33892-add-conan-install-instructions.yml new file mode 100644 index 00000000000..0a308dbdaf9 --- /dev/null +++ b/changelogs/unreleased/33892-add-conan-install-instructions.yml @@ -0,0 +1,5 @@ +--- +title: Added Conan installation instructions to Conan package details page +merge_request: 22390 +author: +type: added diff --git a/changelogs/unreleased/dz-rename-plugins.yml b/changelogs/unreleased/dz-rename-plugins.yml new file mode 100644 index 00000000000..024897d3d65 --- /dev/null +++ b/changelogs/unreleased/dz-rename-plugins.yml @@ -0,0 +1,5 @@ +--- +title: Rename GitLab Plugins feature to GitLab File Hooks +merge_request: 22979 +author: +type: changed diff --git a/changelogs/unreleased/fj-remove-storage-version-from-snippets.yml b/changelogs/unreleased/fj-remove-storage-version-from-snippets.yml deleted file mode 100644 index ee73b903bc6..00000000000 --- a/changelogs/unreleased/fj-remove-storage-version-from-snippets.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Remove storage_version column from snippets -merge_request: 23004 -author: -type: changed diff --git a/changelogs/unreleased/remove_milestone_id_from_epics2.yml b/changelogs/unreleased/remove_milestone_id_from_epics2.yml new file mode 100644 index 00000000000..4ec65150e72 --- /dev/null +++ b/changelogs/unreleased/remove_milestone_id_from_epics2.yml @@ -0,0 +1,5 @@ +--- +title: Remove milestone_id from epics +merge_request: 20539 +author: Lee Tickett +type: other diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml index 6e12eed692f..2986431f21b 100644 --- a/config/sidekiq_queues.yml +++ b/config/sidekiq_queues.yml @@ -76,7 +76,7 @@ - [pages_domain_ssl_renewal, 1] - [object_storage_upload, 1] - [object_storage, 1] - - [plugin, 1] + - [file_hook, 1] - [pipeline_background, 1] - [repository_update_remote_mirror, 1] - [repository_remove_remote, 1] diff --git a/db/post_migrate/20191114204343_remove_milestone_id_from_epics.rb b/db/post_migrate/20191114204343_remove_milestone_id_from_epics.rb new file mode 100644 index 00000000000..4ef6decda95 --- /dev/null +++ b/db/post_migrate/20191114204343_remove_milestone_id_from_epics.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class RemoveMilestoneIdFromEpics < ActiveRecord::Migration[5.2] + DOWNTIME = false + + def up + remove_column :epics, :milestone_id + end + + def down + add_column :epics, :milestone_id, :integer + end +end diff --git a/db/post_migrate/20200114180546_remove_storage_version_column_from_snippets.rb b/db/post_migrate/20200114180546_remove_storage_version_column_from_snippets.rb deleted file mode 100644 index 6aa545a1787..00000000000 --- a/db/post_migrate/20200114180546_remove_storage_version_column_from_snippets.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -class RemoveStorageVersionColumnFromSnippets < ActiveRecord::Migration[5.2] - include Gitlab::Database::MigrationHelpers - - DOWNTIME = false - - disable_ddl_transaction! - - def up - return unless column_exists?(:snippets, :storage_version) - - remove_column :snippets, :storage_version - end - - def down - add_column_with_default( # rubocop:disable Migration/AddColumnWithDefault - :snippets, - :storage_version, - :integer, - default: 2, - allow_null: false - ) - end -end diff --git a/db/schema.rb b/db/schema.rb index a154f7fa993..956c7a30970 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: 2020_01_14_180546) do +ActiveRecord::Schema.define(version: 2020_01_14_113341) do # These are extensions that must be enabled in order to support this database enable_extension "pg_trgm" @@ -1538,7 +1538,6 @@ ActiveRecord::Schema.define(version: 2020_01_14_180546) do end create_table "epics", id: :serial, force: :cascade do |t| - t.integer "milestone_id" t.integer "group_id", null: false t.integer "author_id", null: false t.integer "assignee_id" @@ -1577,7 +1576,6 @@ ActiveRecord::Schema.define(version: 2020_01_14_180546) do t.index ["end_date"], name: "index_epics_on_end_date" t.index ["group_id"], name: "index_epics_on_group_id" t.index ["iid"], name: "index_epics_on_iid" - t.index ["milestone_id"], name: "index_milestone" t.index ["parent_id"], name: "index_epics_on_parent_id" t.index ["start_date"], name: "index_epics_on_start_date" t.index ["start_date_sourcing_epic_id"], name: "index_epics_on_start_date_sourcing_epic_id", where: "(start_date_sourcing_epic_id IS NOT NULL)" @@ -3838,6 +3836,7 @@ ActiveRecord::Schema.define(version: 2020_01_14_180546) do t.string "encrypted_secret_token_iv", limit: 255 t.boolean "secret", default: false, null: false t.string "repository_storage", limit: 255, default: "default", null: false + t.integer "storage_version", default: 2, null: false t.index ["author_id"], name: "index_snippets_on_author_id" t.index ["content"], name: "index_snippets_on_content_trigram", opclass: :gin_trgm_ops, using: :gin t.index ["created_at"], name: "index_snippets_on_created_at" @@ -4590,7 +4589,6 @@ ActiveRecord::Schema.define(version: 2020_01_14_180546) do add_foreign_key "epics", "epics", column: "start_date_sourcing_epic_id", name: "fk_9d480c64b2", on_delete: :nullify add_foreign_key "epics", "milestones", column: "due_date_sourcing_milestone_id", name: "fk_3c1fd1cccc", on_delete: :nullify add_foreign_key "epics", "milestones", column: "start_date_sourcing_milestone_id", name: "fk_1fbed67632", on_delete: :nullify - add_foreign_key "epics", "milestones", on_delete: :nullify add_foreign_key "epics", "namespaces", column: "group_id", name: "fk_f081aa4489", on_delete: :cascade add_foreign_key "epics", "users", column: "assignee_id", name: "fk_dccd3f98fc", on_delete: :nullify add_foreign_key "epics", "users", column: "author_id", name: "fk_3654b61b03", on_delete: :cascade diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md index 6388fe34135..d5e141459b6 100644 --- a/doc/administration/audit_events.md +++ b/doc/administration/audit_events.md @@ -107,7 +107,7 @@ recorded: - Started/stopped user impersonation It is possible to filter particular actions by choosing an audit data type from -the filter drop-down. You can further filter by specific group, project or user +the filter dropdown box. You can further filter by specific group, project or user (for authentication events). ![audit log](img/audit_log.png) diff --git a/doc/administration/file_hooks.md b/doc/administration/file_hooks.md new file mode 100644 index 00000000000..5ef739a4289 --- /dev/null +++ b/doc/administration/file_hooks.md @@ -0,0 +1,116 @@ +# File hooks + +> Introduced in GitLab 10.6. +> Until 12.8 the feature name was Plugins. + +With custom file hooks, GitLab administrators can introduce custom integrations +without modifying GitLab's source code. + +NOTE: **Note:** +Instead of writing and supporting your own file hook you can make changes +directly to the GitLab source code and contribute back upstream. This way we can +ensure functionality is preserved across versions and covered by tests. + +NOTE: **Note:** +File hooks must be configured on the filesystem of the GitLab server. Only GitLab +server administrators will be able to complete these tasks. Explore +[system hooks] or [webhooks] as an option if you do not have filesystem access. + +A file hook will run on each event so it's up to you to filter events or projects +within a file hook code. You can have as many file hooks as you want. Each file hook will +be triggered by GitLab asynchronously in case of an event. For a list of events +see the [system hooks] documentation. + +## Setup + +The file hooks must be placed directly into the `plugins` directory, subdirectories +will be ignored. There is an +[`example` directory inside `plugins`](https://gitlab.com/gitlab-org/gitlab/tree/master/plugins/examples) +where you can find some basic examples. + +Follow the steps below to set up a custom hook: + +1. On the GitLab server, navigate to the plugin directory. + For an installation from source the path is usually + `/home/git/gitlab/plugins/`. For Omnibus installs the path is + usually `/opt/gitlab/embedded/service/gitlab-rails/plugins`. + + For [highly available] configurations, your hook file should exist on each + application server. + +1. Inside the `plugins` directory, create a file with a name of your choice, + without spaces or special characters. +1. Make the hook file executable and make sure it's owned by the Git user. +1. Write the code to make the file hook function as expected. That can be + in any language, and ensure the 'shebang' at the top properly reflects the + language type. For example, if the script is in Ruby the shebang will + probably be `#!/usr/bin/env ruby`. +1. The data to the file hook will be provided as JSON on STDIN. It will be exactly + same as for [system hooks] + +That's it! Assuming the file hook code is properly implemented, the hook will fire +as appropriate. The file hooks file list is updated for each event, there is no +need to restart GitLab to apply a new file hook. + +If a file hook executes with non-zero exit code or GitLab fails to execute it, a +message will be logged to: + +- `gitlab-rails/plugin.log` in an Omnibus installation. +- `log/plugin.log` in a source installation. + +## Creating file hooks + +Below is an example that will only response on the event `project_create` and +will inform the admins from the GitLab instance that a new project has been created. + +```ruby +# By using the embedded ruby version we eliminate the possibility that our chosen language +# would be unavailable from +#!/opt/gitlab/embedded/bin/ruby +require 'json' +require 'mail' + +# The incoming variables are in JSON format so we need to parse it first. +ARGS = JSON.parse(STDIN.read) + +# We only want to trigger this file hook on the event project_create +return unless ARGS['event_name'] == 'project_create' + +# We will inform our admins of our gitlab instance that a new project is created +Mail.deliver do + from 'info@gitlab_instance.com' + to 'admin@gitlab_instance.com' + subject "new project " + ARGS['name'] + body ARGS['owner_name'] + 'created project ' + ARGS['name'] +end +``` + +## Validation + +Writing your own file hook can be tricky and it's easier if you can check it +without altering the system. A rake task is provided so that you can use it +in a staging environment to test your file hook before using it in production. +The rake task will use a sample data and execute each of file hook. The output +should be enough to determine if the system sees your file hook and if it was +executed without errors. + +```bash +# Omnibus installations +sudo gitlab-rake file_hooks:validate + +# Installations from source +cd /home/git/gitlab +bundle exec rake file_hooks:validate RAILS_ENV=production +``` + +Example of output: + +``` +Validating file hooks from /plugins directory +* /home/git/gitlab/plugins/save_to_file.clj succeed (zero exit code) +* /home/git/gitlab/plugins/save_to_file.rb failure (non-zero exit code) +``` + +[system hooks]: ../system_hooks/system_hooks.md +[webhooks]: ../user/project/integrations/webhooks.md +[highly available]: ./high_availability/README.md diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md index eb7a2d791c1..62bacf9791e 100644 --- a/doc/administration/monitoring/prometheus/index.md +++ b/doc/administration/monitoring/prometheus/index.md @@ -245,7 +245,7 @@ To add a Prometheus dashboard for a single server GitLab setup: 1. Create a new data source in Grafana. 1. Name your data source i.e GitLab. -1. Select `Prometheus` in the type drop down. +1. Select `Prometheus` in the type dropdown box. 1. Add your Prometheus listen address as the URL and set access to `Browser`. 1. Set the HTTP method to `GET`. 1. Save & Test your configuration to verify that it works. diff --git a/doc/administration/plugins.md b/doc/administration/plugins.md index 6e4e445ef8f..dbb733b9b19 100644 --- a/doc/administration/plugins.md +++ b/doc/administration/plugins.md @@ -1,115 +1,5 @@ -# GitLab Plugin system +--- +redirect_to: 'file_hooks.md' +--- -> Introduced in GitLab 10.6. - -With custom plugins, GitLab administrators can introduce custom integrations -without modifying GitLab's source code. - -NOTE: **Note:** -Instead of writing and supporting your own plugin you can make changes -directly to the GitLab source code and contribute back upstream. This way we can -ensure functionality is preserved across versions and covered by tests. - -NOTE: **Note:** -Plugins must be configured on the filesystem of the GitLab server. Only GitLab -server administrators will be able to complete these tasks. Explore -[system hooks] or [webhooks] as an option if you do not have filesystem access. - -A plugin will run on each event so it's up to you to filter events or projects -within a plugin code. You can have as many plugins as you want. Each plugin will -be triggered by GitLab asynchronously in case of an event. For a list of events -see the [system hooks] documentation. - -## Setup - -The plugins must be placed directly into the `plugins` directory, subdirectories -will be ignored. There is an -[`example` directory inside `plugins`](https://gitlab.com/gitlab-org/gitlab/tree/master/plugins/examples) -where you can find some basic examples. - -Follow the steps below to set up a custom hook: - -1. On the GitLab server, navigate to the plugin directory. - For an installation from source the path is usually - `/home/git/gitlab/plugins/`. For Omnibus installs the path is - usually `/opt/gitlab/embedded/service/gitlab-rails/plugins`. - - For [highly available] configurations, your hook file should exist on each - application server. - -1. Inside the `plugins` directory, create a file with a name of your choice, - without spaces or special characters. -1. Make the hook file executable and make sure it's owned by the Git user. -1. Write the code to make the plugin function as expected. That can be - in any language, and ensure the 'shebang' at the top properly reflects the - language type. For example, if the script is in Ruby the shebang will - probably be `#!/usr/bin/env ruby`. -1. The data to the plugin will be provided as JSON on STDIN. It will be exactly - same as for [system hooks] - -That's it! Assuming the plugin code is properly implemented, the hook will fire -as appropriate. The plugins file list is updated for each event, there is no -need to restart GitLab to apply a new plugin. - -If a plugin executes with non-zero exit code or GitLab fails to execute it, a -message will be logged to: - -- `gitlab-rails/plugin.log` in an Omnibus installation. -- `log/plugin.log` in a source installation. - -## Creating plugins - -Below is an example that will only response on the event `project_create` and -will inform the admins from the GitLab instance that a new project has been created. - -```ruby -# By using the embedded ruby version we eliminate the possibility that our chosen language -# would be unavailable from -#!/opt/gitlab/embedded/bin/ruby -require 'json' -require 'mail' - -# The incoming variables are in JSON format so we need to parse it first. -ARGS = JSON.parse(STDIN.read) - -# We only want to trigger this plugin on the event project_create -return unless ARGS['event_name'] == 'project_create' - -# We will inform our admins of our gitlab instance that a new project is created -Mail.deliver do - from 'info@gitlab_instance.com' - to 'admin@gitlab_instance.com' - subject "new project " + ARGS['name'] - body ARGS['owner_name'] + 'created project ' + ARGS['name'] -end -``` - -## Validation - -Writing your own plugin can be tricky and it's easier if you can check it -without altering the system. A rake task is provided so that you can use it -in a staging environment to test your plugin before using it in production. -The rake task will use a sample data and execute each of plugin. The output -should be enough to determine if the system sees your plugin and if it was -executed without errors. - -```bash -# Omnibus installations -sudo gitlab-rake plugins:validate - -# Installations from source -cd /home/git/gitlab -bundle exec rake plugins:validate RAILS_ENV=production -``` - -Example of output: - -``` -Validating plugins from /plugins directory -* /home/git/gitlab/plugins/save_to_file.clj succeed (zero exit code) -* /home/git/gitlab/plugins/save_to_file.rb failure (non-zero exit code) -``` - -[system hooks]: ../system_hooks/system_hooks.md -[webhooks]: ../user/project/integrations/webhooks.md -[highly available]: ./high_availability/README.md +This document was moved to [File Hooks](file_hooks.md), after the Plugins feature was renamed to File Hooks. diff --git a/doc/ci/enable_or_disable_ci.md b/doc/ci/enable_or_disable_ci.md index 44815ff7af4..7c7640e23c3 100644 --- a/doc/ci/enable_or_disable_ci.md +++ b/doc/ci/enable_or_disable_ci.md @@ -44,7 +44,7 @@ To enable or disable GitLab CI/CD Pipelines in your project: - **Private**: Only project members can access pipelines. - **Internal** or **Public**: Pipelines can be set to either **Only Project Members** - or **Everyone With Access** via the drop-down box. + or **Everyone With Access** via the dropdown box. Press **Save changes** for the settings to take effect. diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md index 8165d3edabb..610b21234b1 100644 --- a/doc/install/aws/index.md +++ b/doc/install/aws/index.md @@ -244,7 +244,7 @@ Once the database is created, connect to your new RDS instance to verify access and to install a required extension. You can find the host or endpoint by selecting the instance you just created and -after the details drop down you'll find it labeled as 'Endpoint'. Do not to +after the details dropdown menu you'll find it labeled as 'Endpoint'. Do not to include the colon and port number: ```sh diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md index c789467175a..5baaec79048 100644 --- a/doc/install/azure/index.md +++ b/doc/install/azure/index.md @@ -226,7 +226,7 @@ connections: ![Azure - Add inbound security rules - HTTP](img/azure-add-inbound-sec-rule-http.png) 1. Enter **"HTTP"** in the `Name` field -1. Select **HTTP** from the options in the `Service` drop-down +1. Select **HTTP** from the options in the `Service` dropdown list 1. Make sure the `Action` is set to **Allow** 1. Click **"OK"** @@ -238,7 +238,7 @@ accept [SSH] connections: ![Azure - Add inbound security rules - SSH](img/azure-add-inbound-sec-rule-ssh.png) 1. Enter **"SSH"** in the `Name` field -1. Select **SSH** from the options in the `Service` drop-down +1. Select **SSH** from the options in the `Service` dropdown list 1. Make sure the `Action` is set to **Allow** 1. Click **"OK"** diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md index 08242b3c65b..eb726ee2ed7 100644 --- a/doc/user/application_security/container_scanning/index.md +++ b/doc/user/application_security/container_scanning/index.md @@ -269,6 +269,15 @@ it highlighted: } ], "remediations": [ + { + "fixes": [ + { + "cve": "debian:9:apt:CVE-2019-3462" + } + ], + "summary": "Upgrade apt from 1.4.8 to 1.4.9", + "diff": "YXB0LWdldCB1cGRhdGUgJiYgYXB0LWdldCB1cGdyYWRlIC15IGFwdA==" + } ] } ``` @@ -305,7 +314,11 @@ the report JSON unless stated otherwise. Presence of optional fields depends on | `vulnerabilities[].links` | An array of references to external documentation pieces or articles that describe the vulnerability further. Optional. | | `vulnerabilities[].links[].name` | Name of the vulnerability details link. Optional. | | `vulnerabilities[].links[].url` | URL of the vulnerability details document. Optional. | -| `remediations` | Not supported yet. | +| `remediations` | An array of objects containing information on cured vulnerabilities along with patch diffs to apply. Empty if no remediations provided by an underlying analyzer. | +| `remediations[].fixes` | An array of strings that represent references to vulnerabilities fixed by this particular remediation. | +| `remediations[].fixes[].cve` | A string value that describes a fixed vulnerability occurrence in the same format as `vulnerabilities[].cve`. | +| `remediations[].summary` | Overview of how the vulnerabilities have been fixed. | +| `remediations[].diff` | base64-encoded remediation code diff, compatible with [`git apply`](https://git-scm.com/docs/git-format-patch#_discussion). | ## Troubleshooting diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md index 594f73dbfbe..83fbbd04739 100644 --- a/doc/user/project/issues/design_management.md +++ b/doc/user/project/issues/design_management.md @@ -71,6 +71,8 @@ Designs cannot be added if the issue has been moved, or its ## Viewing designs Images on the Design Management page can be enlarged by clicking on them. +You can navigate through designs by clicking on the navigation buttons on the +top-right corner or with <kbd>Left</kbd>/<kbd>Right</kbd> keyboard buttons. The number of comments on a design — if any — is listed to the right of the design filename. Clicking on this number enlarges the design diff --git a/lib/gitlab/database_importers/self_monitoring/project/delete_service.rb b/lib/gitlab/database_importers/self_monitoring/project/delete_service.rb index bce0819b700..998977b4000 100644 --- a/lib/gitlab/database_importers/self_monitoring/project/delete_service.rb +++ b/lib/gitlab/database_importers/self_monitoring/project/delete_service.rb @@ -9,8 +9,7 @@ module Gitlab include SelfMonitoring::Helpers steps :validate_self_monitoring_project_exists, - :destroy_project_owner, - :delete_project_id + :destroy_project def initialize super(nil) @@ -30,29 +29,16 @@ module Gitlab success(result) end - def destroy_project_owner(result) + def destroy_project(result) return success(result) unless project_created? - if self_monitoring_project.owner.destroy + if self_monitoring_project.destroy success(result) else log_error(self_monitoring_project.errors.full_messages) error(_('Error deleting project. Check logs for error details.')) end end - - def delete_project_id(result) - update_result = application_settings.update( - instance_administration_project_id: nil - ) - - if update_result - success(result) - else - log_error("Could not delete self monitoring project ID, errors: %{errors}" % { errors: application_settings.errors.full_messages }) - error(_('Could not delete project ID')) - end - end end end end diff --git a/lib/gitlab/plugin.rb b/lib/gitlab/file_hook.rb index b6700f4733b..f886fd10f53 100644 --- a/lib/gitlab/plugin.rb +++ b/lib/gitlab/file_hook.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Gitlab - module Plugin + module FileHook def self.any? plugin_glob.any? { |entry| File.file?(entry) } end @@ -17,7 +17,7 @@ module Gitlab def self.execute_all_async(data) args = files.map { |file| [file, data] } - PluginWorker.bulk_perform_async(args) + FileHookWorker.bulk_perform_async(args) end def self.execute(file, data) diff --git a/lib/gitlab/plugin_logger.rb b/lib/gitlab/file_hook_logger.rb index df3bd56fd2f..c5e69172016 100644 --- a/lib/gitlab/plugin_logger.rb +++ b/lib/gitlab/file_hook_logger.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Gitlab - class PluginLogger < Gitlab::Logger + class FileHookLogger < Gitlab::Logger def self.file_name_noext 'plugin' end diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb index d9300da38a5..48eaf073e8a 100644 --- a/lib/gitlab/regex.rb +++ b/lib/gitlab/regex.rb @@ -5,7 +5,7 @@ module Gitlab extend self def project_name_regex - @project_name_regex ||= /\A[\p{Alnum}\u{00A9}-\u{1f9c0}_][\p{Alnum}\p{Pd}\u{00A9}-\u{1f9c0}_\. ]*\z/.freeze + @project_name_regex ||= /\A[\p{Alnum}\u{00A9}-\u{1f9ff}_][\p{Alnum}\p{Pd}\u{00A9}-\u{1f9ff}_\. ]*\z/.freeze end def project_name_regex_message diff --git a/lib/tasks/plugins.rake b/lib/tasks/file_hooks.rake index e73dd7e68df..20a726de65b 100644 --- a/lib/tasks/plugins.rake +++ b/lib/tasks/file_hooks.rake @@ -1,10 +1,10 @@ -namespace :plugins do +namespace :file_hooks do desc 'Validate existing plugins' task validate: :environment do - puts 'Validating plugins from /plugins directory' + puts 'Validating file hooks from /plugins directory' - Gitlab::Plugin.files.each do |file| - success, message = Gitlab::Plugin.execute(file, Gitlab::DataBuilder::Push::SAMPLE_DATA) + Gitlab::FileHook.files.each do |file| + success, message = Gitlab::FileHook.execute(file, Gitlab::DataBuilder::Push::SAMPLE_DATA) if success puts "* #{file} succeed (zero exit code)." diff --git a/locale/gitlab.pot b/locale/gitlab.pot index a1b93afec2f..15b16d3b43a 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -5187,9 +5187,6 @@ msgstr "" msgid "Could not delete chat nickname %{chat_name}." msgstr "" -msgid "Could not delete project ID" -msgstr "" - msgid "Could not fetch projects" msgstr "" @@ -7992,6 +7989,12 @@ msgstr "" msgid "Fetching licenses failed. You are not permitted to perform this action." msgstr "" +msgid "File Hooks" +msgstr "" + +msgid "File Hooks (%{count})" +msgstr "" + msgid "File added" msgstr "" @@ -8001,6 +8004,9 @@ msgstr "" msgid "File deleted" msgstr "" +msgid "File hooks are similar to system hooks but are executed as files instead of sending data to a URL." +msgstr "" + msgid "File mode changed from %{a_mode} to %{b_mode}" msgstr "" @@ -8166,6 +8172,9 @@ msgstr "" msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}" msgstr "" +msgid "For more information, see the File Hooks documentation." +msgstr "" + msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}." msgstr "" @@ -12203,6 +12212,9 @@ msgstr "" msgid "No file chosen" msgstr "" +msgid "No file hooks found." +msgstr "" + msgid "No file selected" msgstr "" @@ -12775,6 +12787,18 @@ msgstr "" msgid "Package was removed" msgstr "" +msgid "PackageRegistry|Add Conan Remote" +msgstr "" + +msgid "PackageRegistry|Conan Command" +msgstr "" + +msgid "PackageRegistry|Copy Conan Command" +msgstr "" + +msgid "PackageRegistry|Copy Conan Setup Command" +msgstr "" + msgid "PackageRegistry|Copy Maven XML" msgstr "" @@ -12805,6 +12829,9 @@ msgstr "" msgid "PackageRegistry|Delete package" msgstr "" +msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}." +msgstr "" + msgid "PackageRegistry|For more information on the Maven registry, %{linkStart}see the documentation%{linkEnd}." msgstr "" @@ -18642,6 +18669,9 @@ msgstr "" msgid "There was an error while fetching cycle analytics duration data." msgstr "" +msgid "There was an error while fetching cycle analytics duration median data." +msgstr "" + msgid "There was an error while fetching cycle analytics summary data." msgstr "" diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb index b4bcbe9d812..64326f3be32 100644 --- a/spec/features/admin/admin_hooks_spec.rb +++ b/spec/features/admin/admin_hooks_spec.rb @@ -28,11 +28,11 @@ describe 'Admin::Hooks' do end it 'renders plugins list as well' do - allow(Gitlab::Plugin).to receive(:files).and_return(['foo.rb', 'bar.clj']) + allow(Gitlab::FileHook).to receive(:files).and_return(['foo.rb', 'bar.clj']) visit admin_hooks_path - expect(page).to have_content('Plugins') + expect(page).to have_content('File Hooks') expect(page).to have_content('foo.rb') expect(page).to have_content('bar.clj') end diff --git a/spec/features/projects/settings/user_renames_a_project_spec.rb b/spec/features/projects/settings/user_renames_a_project_spec.rb index d2daf8b922d..789c5e31748 100644 --- a/spec/features/projects/settings/user_renames_a_project_spec.rb +++ b/spec/features/projects/settings/user_renames_a_project_spec.rb @@ -59,8 +59,8 @@ describe 'Projects > Settings > User renames a project' do context 'with emojis' do it 'shows error for invalid project name' do - change_name(project, '🚀 foo bar ☁️') - expect(page).to have_field 'Project name', with: '🚀 foo bar ☁️' + change_name(project, '🧮 foo bar ☁️') + expect(page).to have_field 'Project name', with: '🧮 foo bar ☁️' expect(page).not_to have_content "Name can contain only letters, digits, emojis '_', '.', dash and space. It must start with letter, digit, emoji or '_'." end end diff --git a/spec/finders/group_members_finder_spec.rb b/spec/finders/group_members_finder_spec.rb index 5636b5db84f..34649097f70 100644 --- a/spec/finders/group_members_finder_spec.rb +++ b/spec/finders/group_members_finder_spec.rb @@ -57,6 +57,14 @@ describe GroupMembersFinder, '#execute' do expect(result.to_a).to match_array([member1]) end + it 'does not return nil if `inherited only` relation is requested on root group' do + group.add_developer(user2) + + result = described_class.new(group).execute(include_relations: [:inherited]) + + expect(result).not_to be_nil + end + it 'returns members for descendant groups if requested' do member1 = group.add_maintainer(user2) member2 = group.add_maintainer(user1) @@ -71,25 +79,41 @@ describe GroupMembersFinder, '#execute' do it 'returns searched members if requested' do group.add_maintainer(user2) - nested_group.add_maintainer(user2) - nested_group.add_maintainer(user3) - nested_group.add_maintainer(user4) + group.add_developer(user3) member = group.add_maintainer(user1) - result = described_class.new(group).execute(include_relations: [:direct, :descendants], params: { search: user1.name }) + result = described_class.new(group).execute(params: { search: user1.name }) expect(result.to_a).to match_array([member]) end + it 'returns nothing if search only in inherited relation' do + group.add_maintainer(user2) + group.add_developer(user3) + group.add_maintainer(user1) + + result = described_class.new(group).execute(include_relations: [:inherited], params: { search: user1.name }) + + expect(result.to_a).to match_array([]) + end + + it 'returns searched member only from nested_group if search only in inherited relation' do + group.add_maintainer(user2) + group.add_developer(user3) + nested_group.add_maintainer(create(:user, name: user1.name)) + member = group.add_maintainer(user1) + + result = described_class.new(nested_group).execute(include_relations: [:inherited], params: { search: member.user.name }) + + expect(result.to_a).to contain_exactly(member) + end + it 'returns members with two-factor auth if requested by owner' do group.add_owner(user2) group.add_maintainer(user1) - nested_group.add_maintainer(user2) - nested_group.add_maintainer(user3) - nested_group.add_maintainer(user4) member = group.add_maintainer(user5) - result = described_class.new(group, user2).execute(include_relations: [:direct, :descendants], params: { two_factor: 'enabled' }) + result = described_class.new(group, user2).execute(params: { two_factor: 'enabled' }) expect(result.to_a).to contain_exactly(member) end @@ -97,14 +121,11 @@ describe GroupMembersFinder, '#execute' do it 'returns members without two-factor auth if requested by owner' do member1 = group.add_owner(user2) member2 = group.add_maintainer(user1) - nested_group.add_maintainer(user2) - member3 = nested_group.add_maintainer(user3) - member4 = nested_group.add_maintainer(user4) member_with_2fa = group.add_maintainer(user5) - result = described_class.new(group, user2).execute(include_relations: [:direct, :descendants], params: { two_factor: 'disabled' }) + result = described_class.new(group, user2).execute(params: { two_factor: 'disabled' }) expect(result.to_a).not_to include(member_with_2fa) - expect(result.to_a).to match_array([member1, member2, member3, member4]) + expect(result.to_a).to match_array([member1, member2]) end end diff --git a/spec/lib/gitlab/database_importers/self_monitoring/project/delete_service_spec.rb b/spec/lib/gitlab/database_importers/self_monitoring/project/delete_service_spec.rb index b0cec61ce06..6446ab1beb4 100644 --- a/spec/lib/gitlab/database_importers/self_monitoring/project/delete_service_spec.rb +++ b/spec/lib/gitlab/database_importers/self_monitoring/project/delete_service_spec.rb @@ -4,12 +4,8 @@ require 'spec_helper' describe Gitlab::DatabaseImporters::SelfMonitoring::Project::DeleteService do describe '#execute' do + let!(:application_setting) { create(:application_setting) } let(:result) { subject.execute } - let(:application_setting) { Gitlab::CurrentSettings.current_application_settings } - - before do - allow(ApplicationSetting).to receive(:current_without_cache) { application_setting } - end context 'when project does not exist' do it 'returns error' do @@ -21,24 +17,16 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::DeleteService do end end - context 'with project destroyed but ID still present in application settings' do - before do - application_setting.instance_administration_project_id = 1 - end - - it 'deletes project ID from application settings' do - subject.execute - - expect(application_setting.instance_administration_project_id).to be_nil - end - end - context 'when self monitoring project exists' do let(:group) { create(:group) } let(:project) { create(:project, namespace: group) } - before do - application_setting.instance_administration_project = project + let(:application_setting) do + create( + :application_setting, + instance_administration_project_id: project.id, + instance_administrators_group_id: group.id + ) end it 'destroys project' do @@ -50,7 +38,13 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::DeleteService do it 'deletes project ID from application settings' do subject.execute - expect(application_setting.instance_administration_project_id).to be_nil + expect(application_setting.reload.instance_administration_project_id).to be_nil + end + + it 'does not delete group' do + subject.execute + + expect(application_setting.instance_administrators_group).to eq(group) end end end diff --git a/spec/lib/gitlab/plugin_spec.rb b/spec/lib/gitlab/file_hook_spec.rb index 5d9f6d04caa..d184eb483d4 100644 --- a/spec/lib/gitlab/plugin_spec.rb +++ b/spec/lib/gitlab/file_hook_spec.rb @@ -2,11 +2,11 @@ require 'spec_helper' -describe Gitlab::Plugin do - let(:plugin) { Rails.root.join('plugins', 'test.rb') } - let(:tmp_file) { Tempfile.new('plugin-dump') } +describe Gitlab::FileHook do + let(:file_hook) { Rails.root.join('plugins', 'test.rb') } + let(:tmp_file) { Tempfile.new('file_hook-dump') } - let(:plugin_source) do + let(:file_hook_source) do <<~EOS #!/usr/bin/env ruby x = STDIN.read @@ -14,13 +14,13 @@ describe Gitlab::Plugin do EOS end - context 'with plugins present' do + context 'with file_hooks present' do before do - File.write(plugin, plugin_source) + File.write(file_hook, file_hook_source) end after do - FileUtils.rm(plugin) + FileUtils.rm(file_hook) end describe '.any?' do @@ -30,13 +30,13 @@ describe Gitlab::Plugin do end describe '.files?' do - it 'returns a list of plugins' do - expect(described_class.files).to match_array([plugin.to_s]) + it 'returns a list of file_hooks' do + expect(described_class.files).to match_array([file_hook.to_s]) end end end - context 'without any plugins' do + context 'without any file_hooks' do describe '.any?' do it 'returns false' do expect(described_class.any?).to be false @@ -52,21 +52,21 @@ describe Gitlab::Plugin do describe '.execute' do let(:data) { Gitlab::DataBuilder::Push::SAMPLE_DATA } - let(:result) { described_class.execute(plugin.to_s, data) } + let(:result) { described_class.execute(file_hook.to_s, data) } let(:success) { result.first } let(:message) { result.last } before do - File.write(plugin, plugin_source) + File.write(file_hook, file_hook_source) end after do - FileUtils.rm(plugin) + FileUtils.rm(file_hook) end context 'successful execution' do before do - File.chmod(0o777, plugin) + File.chmod(0o777, file_hook) end after do @@ -76,7 +76,7 @@ describe Gitlab::Plugin do it { expect(success).to be true } it { expect(message).to be_empty } - it 'ensures plugin received data via stdin' do + it 'ensures file_hook received data via stdin' do result expect(File.read(tmp_file.path)).to eq(data.to_json) @@ -89,7 +89,7 @@ describe Gitlab::Plugin do end context 'non-zero exit' do - let(:plugin_source) do + let(:file_hook_source) do <<~EOS #!/usr/bin/env ruby exit 1 @@ -97,7 +97,7 @@ describe Gitlab::Plugin do end before do - File.chmod(0o777, plugin) + File.chmod(0o777, file_hook) end it { expect(success).to be false } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index e3d9ffcfff1..c57f47b5738 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -4745,7 +4745,7 @@ describe Project do end it 'returns true when a plugin exists' do - expect(Gitlab::Plugin).to receive(:any?).twice.and_return(true) + expect(Gitlab::FileHook).to receive(:any?).twice.and_return(true) expect(project.has_active_hooks?(:merge_request_events)).to be_truthy expect(project.has_active_hooks?).to be_truthy diff --git a/spec/workers/file_hook_worker_spec.rb b/spec/workers/file_hook_worker_spec.rb new file mode 100644 index 00000000000..1a7e753fc4a --- /dev/null +++ b/spec/workers/file_hook_worker_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe FileHookWorker do + include RepoHelpers + + let(:filename) { 'my_file_hook.rb' } + let(:data) { { 'event_name' => 'project_create' } } + + subject { described_class.new } + + describe '#perform' do + it 'executes Gitlab::FileHook with expected values' do + allow(Gitlab::FileHook).to receive(:execute).with(filename, data).and_return([true, '']) + + expect(subject.perform(filename, data)).to be_truthy + end + + it 'logs message in case of file_hook execution failure' do + allow(Gitlab::FileHook).to receive(:execute).with(filename, data).and_return([false, 'permission denied']) + + expect(Gitlab::FileHookLogger).to receive(:error) + expect(subject.perform(filename, data)).to be_truthy + end + end +end diff --git a/spec/workers/plugin_worker_spec.rb b/spec/workers/plugin_worker_spec.rb deleted file mode 100644 index ca6c9986131..00000000000 --- a/spec/workers/plugin_worker_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe PluginWorker do - include RepoHelpers - - let(:filename) { 'my_plugin.rb' } - let(:data) { { 'event_name' => 'project_create' } } - - subject { described_class.new } - - describe '#perform' do - it 'executes Gitlab::Plugin with expected values' do - allow(Gitlab::Plugin).to receive(:execute).with(filename, data).and_return([true, '']) - - expect(subject.perform(filename, data)).to be_truthy - end - - it 'logs message in case of plugin execution failure' do - allow(Gitlab::Plugin).to receive(:execute).with(filename, data).and_return([false, 'permission denied']) - - expect(Gitlab::PluginLogger).to receive(:error) - expect(subject.perform(filename, data)).to be_truthy - end - end -end |