diff options
31 files changed, 439 insertions, 115 deletions
diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 9e7501b7ce6..3000ab7cad0 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -283,6 +283,10 @@ class Snippet < ApplicationRecord end end + def url_to_repo + Gitlab::Shell.url_to_repo(full_path.delete('@')) + end + def repository_storage snippet_repository&.shard_name || Gitlab::CurrentSettings.pick_repository_storage diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml index d7619799f14..c11d1256d21 100644 --- a/app/views/layouts/nav/sidebar/_project.html.haml +++ b/app/views/layouts/nav/sidebar/_project.html.haml @@ -159,6 +159,8 @@ %span.badge.badge-pill.count.merge_counter.js-merge-counter.fly-out-badge = number_with_delimiter(@project.open_merge_requests_count) + = render_if_exists "layouts/nav/requirements_link", project: @project + - if project_nav_tab? :pipelines = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :artifacts], unless: -> { current_path?('projects/pipelines#charts') }) do = link_to project_pipelines_path(@project), class: 'shortcuts-pipelines qa-link-pipelines rspec-link-pipelines', data: { qa_selector: 'ci_cd_link' } do diff --git a/app/workers/concerns/application_worker.rb b/app/workers/concerns/application_worker.rb index 733156ab758..c0062780688 100644 --- a/app/workers/concerns/application_worker.rb +++ b/app/workers/concerns/application_worker.rb @@ -13,6 +13,17 @@ module ApplicationWorker included do set_queue + + def structured_payload(payload = {}) + context = Labkit::Context.current.to_h.merge( + 'class' => self.class, + 'job_status' => 'running', + 'queue' => self.class.queue, + 'jid' => jid + ) + + payload.stringify_keys.merge(context) + end end class_methods do diff --git a/changelogs/unreleased/fj-205646-fix-project-moved-message.yml b/changelogs/unreleased/fj-205646-fix-project-moved-message.yml new file mode 100644 index 00000000000..9f5865d78ef --- /dev/null +++ b/changelogs/unreleased/fj-205646-fix-project-moved-message.yml @@ -0,0 +1,5 @@ +--- +title: Fix project moved message after git operation +merge_request: 27341 +author: +type: fixed diff --git a/changelogs/unreleased/fj-fix-snippet-url-to-repo.yml b/changelogs/unreleased/fj-fix-snippet-url-to-repo.yml new file mode 100644 index 00000000000..8f84d3ad9f5 --- /dev/null +++ b/changelogs/unreleased/fj-fix-snippet-url-to-repo.yml @@ -0,0 +1,5 @@ +--- +title: Fix remove special chars from snippet url_to_repo +merge_request: 27390 +author: +type: fixed diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml index 9f52b422fec..2dc2f33e71e 100644 --- a/config/sidekiq_queues.yml +++ b/config/sidekiq_queues.yml @@ -232,6 +232,8 @@ - 2 - - service_desk_email_receiver - 1 +- - status_page_publish_incident + - 1 - - sync_seat_link_request - 1 - - system_hook_push diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md index 6f1f49ddf84..b789f2ddd02 100644 --- a/doc/administration/monitoring/prometheus/gitlab_metrics.md +++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md @@ -182,7 +182,7 @@ Unicorn specific metrics, when Unicorn is used. | `unicorn_queued_connections` | Gauge | 11.0 | The number of queued Unicorn connections | | `unicorn_workers` | Gauge | 12.0 | The number of Unicorn workers | -## Puma Metrics **(EXPERIMENTAL)** +## Puma Metrics When Puma is used instead of Unicorn, the following metrics are available: diff --git a/doc/administration/operations/puma.md b/doc/administration/operations/puma.md index 2490cf1f0ae..30fea36fac6 100644 --- a/doc/administration/operations/puma.md +++ b/doc/administration/operations/puma.md @@ -2,8 +2,8 @@ ## Puma -GitLab plans to use [Puma](https://github.com/puma/puma) to replace -[Unicorn](https://bogomips.org/unicorn/). +As of GitLab 12.9, [Puma](https://github.com/puma/puma) has replaced [Unicorn](https://bogomips.org/unicorn/). +as the default web server. ## Why switch to Puma? diff --git a/doc/administration/packages/dependency_proxy.md b/doc/administration/packages/dependency_proxy.md index 4cbb22668d9..b489d829ba7 100644 --- a/doc/administration/packages/dependency_proxy.md +++ b/doc/administration/packages/dependency_proxy.md @@ -11,9 +11,8 @@ dependency proxies, see the [user guide](../../user/group/dependency_proxy/index NOTE: **Note:** Dependency proxy requires the Puma web server to be enabled. -Puma support is EXPERIMENTAL at this time. -To enable the Dependency proxy feature: +To enable the dependency proxy feature: **Omnibus GitLab installations** @@ -37,7 +36,9 @@ To enable the Dependency proxy feature: ``` 1. [Restart GitLab](../restart_gitlab.md#installations-from-source "How to restart GitLab") for the changes to take effect. -1. Enable the [Puma web server](../../install/installation.md#using-puma). + +Since Puma is already the default web server for installations from source as of GitLab 12.9, +no further changes are needed. ## Changing the storage path diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md index 08d0cb6d691..ce7d2fa3e73 100644 --- a/doc/administration/pages/index.md +++ b/doc/administration/pages/index.md @@ -566,6 +566,51 @@ GitLab Pages are part of the [regular backup][backup], so there is no separate b You should strongly consider running GitLab Pages under a different hostname than GitLab to prevent XSS attacks. +<!-- ## Troubleshooting + +Include any troubleshooting steps that you can foresee. If you know beforehand what issues +one might have when setting this up, or when something is changed, or on upgrading, it's +important to describe those, too. Think of things that may go wrong and include them here. +This is important to minimize requests for support, and to avoid doc comments with +questions that you know someone might ask. + +Each scenario can be a third-level heading, e.g. `### Getting error message X`. +If you have none to add when creating a doc, leave this section in place +but commented out to help encourage others to add to it in the future. --> + +## Troubleshooting + +### `open /etc/ssl/ca-bundle.pem: permission denied` + +GitLab Pages runs inside a `chroot` jail, usually in a uniquely numbered directory like +`/tmp/gitlab-pages-*`. + +Within the jail, a bundle of trusted certificates is +provided at `/etc/ssl/ca-bundle.pem`. It's +[copied there](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/51) +from `/opt/gitlab/embedded/ssl/certs/cacert.pem` +as part of starting up Pages. + +If the permissions on the source file are incorrect (they should be `0644`) then +the file inside the `chroot` jail will also be wrong. + +Pages will log errors in `/var/log/gitlab/gitlab-pages/current` like: + +```plaintext +x509: failed to load system roots and no roots provided +open /etc/ssl/ca-bundle.pem: permission denied +``` + +The use of a `chroot` jail makes this error misleading, as it is not +referring to `/etc/ssl` on the root filesystem. + +The fix is to correct the source file permissions and restart Pages: + +```shell +sudo chmod 644 /opt/gitlab/embedded/ssl/certs/cacert.pem +sudo gitlab-ctl restart gitlab-pages +``` + [backup]: ../../raketasks/backup_restore.md [ce-14605]: https://gitlab.com/gitlab-org/gitlab-foss/issues/14605 [ee-80]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80 diff --git a/doc/development/README.md b/doc/development/README.md index 75dc54050d8..bc5f50b0499 100644 --- a/doc/development/README.md +++ b/doc/development/README.md @@ -163,6 +163,7 @@ Complementary reads: - [Jira Connect app](integrations/jira_connect.md) - [Security Scanners](integrations/secure.md) +- [Secure Partner Integration](integrations/secure_partner_integration.md) ## Testing guides diff --git a/doc/development/integrations/secure_partner_integration.md b/doc/development/integrations/secure_partner_integration.md new file mode 100644 index 00000000000..9991ee57257 --- /dev/null +++ b/doc/development/integrations/secure_partner_integration.md @@ -0,0 +1,103 @@ +# Secure Partner Integration - Onboarding Process + +If you want to integrate your product with the [Secure Stage](https://about.gitlab.com/direction/secure), +this page will help you understand the developer workflow GitLab intends for +our users to follow with regards to security results. These should be used as +guidelines so you can build an integration that fits with the workflow GitLab +users are already familiar with. + +This page also provides resources for the technical work associated +with [onboarding as a partner](https://about.gitlab.com/partners/integrate/). +The steps below are a high-level view of what needs to be done to complete an +integration as well as linking to more detailed resources for how to do so. + +## What is the GitLab Developer Workflow? + +This workflow is how GitLab users interact with our product and expect it to +function. Understanding how users use GitLab today will help you choose the +best place to integrate your own product and its results into GitLab. + +- Developers want to write code without using a new tool to consume results + or address feedback about the item they are working on. Staying inside a + single tool, GitLab, helps them to stay focused on finishing the code and + projects they are working on. +- Developers commit code to a Git branch. The developer creates a merge request (MR) + inside GitLab where these changes can be reviewed. The MR triggers a GitLab + pipeline to run associated jobs, including security checks, on the code. +- Pipeline jobs serve a variety of purposes. Jobs can do scanning for and have + implications for app security, corporate policy, or compliance. When complete, + the job reports back on its status and creates a + [job artifact](../../user/project/pipelines/job_artifacts.md) as a result. +- The [Merge Request Security Widget](../../user/project/merge_requests/index.md#security-reports-ultimate) + displays the results of the pipeline's security checks and the developer can + review them. The developer can review both a summary and a detailed version + of the results. +- If certain policies (such as [merge request approvals](../../user/project/merge_requests/merge_request_approvals.md)) + are in place for a project, developers must resolve specific findings or get + an approval from a specific list of people. +- The [security dashboard](../../user/application_security/security_dashboard/index.md#gitlab-security-dashboard-ultimate) + also shows results which can developers can use to quickly see all the + vulnerabilities that need to be addressed in the code. +- When the developer reads the details about a vulnerability, they are + presented with additional information and choices on next steps: + 1. Create Issue (Confirm finding): Creates a new issue to be prioritized. + 1. Add Comment and Dismiss Vulnerability: When dismissing a finding, users + can comment to note items that they + have mitigated, that they accept the vulnerability, or that the + vulnerability is a false positive. + 1. Auto-Remediation / Create Merge Request: A fix for the vulnerability can + be offered, allowing an easy solution that does not require extra effort + from users. This should be offered whenever possible. + 1. Links: Vulnerabilities can link out external sites or sources for users + to get more data around the vulnerability. + +## How to onboard + +This section describes the steps you need to complete to onboard as a partner +and complete an intgration with the Secure stage. + +1. Read about our [partnerships](https://about.gitlab.com/partners/integrate/index.md). +1. [Create an issue](https://gitlab.com/gitlab-com/alliances/alliances/issues/new?issuable_template=new_partner) + using our new partner issue template to begin the discussion. +1. Get a test account to begin developing your integration. You can + request a [GitLab.com Gold Subscription Sandbox](https://about.gitlab.com/partners/integrate/index.md#gitlabcom-gold-subscription-sandbox-request) + or an [EE Developer License](https://about.gitlab.com/partners/integrate/index.md#requesting-ee-dev-license-for-rd). +1. Provide a [pipeline job](../../development/pipelines.md) + template that users could integrate into their own GitLab pipelines. +1. Create a report artifact with your pipeline jobs. +1. Ensure your pipeline jobs create a report artifact that GitLab can process + to successfully display your own product's results with the rest of GitLab. + - See detailed [technical directions](secure.md) for this step. + - Read more about [job report artifacts](../../ci/yaml/README.md#artifactsreports). + - Read about [job artifacts](../../user/project/pipelines/job_artifacts.md). + - Your report artifact must be in one of our currently supported formats. + For more information, see the [documentation on reports](secure.md#report). + - Documentation for [SAST reports](../../user/application_security/sast/index.md#reports-json-format). + - Documentation for [Dependency Scanning reports](../../user/application_security/dependency_scanning/index.md#reports-json-format). + - Documentation for [Container Scanning reports](../../user/application_security/container_scanning/index.md#reports-json-format). + - See this [example secure job definition that also defines the artifact created](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml). + - If you need a new kind of scan or report, [create an issue](https://gitlab.com/gitlab-org/gitlab/issues/new#) + and add the label `devops::secure`. + - Once the job is completed, the data can be seen: + - In the [Merge Request Security Report](../../user/project/merge_requests/index.md#security-reports-ultimate) ([MR Security Report data flow](https://gitlab.com/snippets/1910005#merge-request-view)). + - While [browsing a Job Artifact](../../user/project/pipelines/job_artifacts.md). + - In the [Security Dashboard](../../user/application_security/security_dashboard/index.md) ([Dashboard data flow](https://gitlab.com/snippets/1910005#project-and-group-dashboards)). +1. Optional: Provide a way to interact with results as Vulnerabilities: + - Users can interact with the findings from your artifact within their workflow. They can dismiss the findings or accept them and create a backlog issue. + - To automatically create issues without user interaction, use the [issue API](../../api/issues.md). This will be replaced by [Standalone Vulnerabilities](https://gitlab.com/groups/gitlab-org/-/epics/634) in the future. +1. Optional: Provide auto-remediation steps: + - If you specified `remediations` in your artifact, it is proposed through our [auto-remediation](../../user/application_security/index.md#solutions-for-vulnerabilities-auto-remediation) + interface. +1. Demo the integration to GitLab: + - After you have tested and are ready to demo your integration please + [reach out](https://about.gitlab.com/partners/integrate/index.md) to us. If you + skip this step you won’t be able to do supported marketing. +1. Begin doing supported marketing of your GitLab integration. + - Work with our [partner team](https://about.gitlab.com/partners/integrate/index.md) + to support your go-to-market as appropriate. + - Examples of supported marketing could include being listed on our [Security Partner page](https://about.gitlab.com/partners/index.md#security), + doing an [Unfiltered blog post](https://about.gitlab.com/handbook/marketing/blog/unfiltered/index.md), + doing a co-branded webinar, or producing a co-branded whitepaper. + +If you have any issues while working through your integration or the steps +above, please create an issue to discuss with us further. diff --git a/doc/install/installation.md b/doc/install/installation.md index c742d9ca464..fa708f6d5cf 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -457,16 +457,13 @@ sudo chmod -R u+rwX shared/artifacts/ # Change the permissions of the directory where GitLab Pages are stored sudo chmod -R ug+rwX shared/pages/ -# Copy the example Unicorn config -sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb +# Copy the example Puma config +sudo -u git -H cp config/puma.rb.example config/puma.rb -# Find number of cores -nproc - -# Enable cluster mode if you expect to have a high load instance -# Set the number of workers to at least the number of cores -# Ex. change the amount of workers to 3 for 2GB RAM server -sudo -u git -H editor config/unicorn.rb +# Refer to https://github.com/puma/puma#configuration for more information. +# You should scale Puma workers and threads based on the number of CPU +# cores you have available. You can get that number via the `nproc` command. +sudo -u git -H editor config/puma.rb # Copy the example Rack attack config sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb @@ -495,8 +492,8 @@ sudo -u git -H editor config/resque.yml ``` CAUTION: **Caution:** -Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup. -If you want to use Puma web server, see [Using Puma](#using-puma) for the additional steps. +Make sure to edit both `gitlab.yml` and `puma.rb` to match your setup. +If you want to use the Unicorn web server, see [Using Unicorn](#using-unicorn) for the additional steps. NOTE: **Note:** If you want to use HTTPS, see [Using HTTPS](#using-https) for the additional steps. @@ -947,23 +944,22 @@ You also need to change the corresponding options (e.g. `ssh_user`, `ssh_host`, Apart from the always supported Markdown style, there are other rich text files that GitLab can display. But you might have to install a dependency to do so. See the [`github-markup` gem README](https://github.com/gitlabhq/markup#markups) for more information. -### Using Puma - -Puma is a multi-threaded HTTP 1.1 server for Ruby applications. +### Using Unicorn -To use GitLab with Puma: +As of GitLab 12.9, [Puma](https://github.com/puma/puma) has replaced Unicorn as the default web server for installations from source. +If you want to switch back to Unicorn, follow these steps: -1. Finish GitLab setup so you have it up and running. -1. Copy the supplied example Puma config file into place: +1. Finish the GitLab setup so you have it up and running. +1. Copy the supplied example Unicorn config file into place: ```shell cd /home/git/gitlab # Copy config file for the web server - sudo -u git -H cp config/puma.rb.example config/puma.rb + sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb ``` -1. Edit the system `init.d` script to use `EXPERIMENTAL_PUMA=1` flag. If you have `/etc/default/gitlab`, then you should edit it instead. +1. Edit the system `init.d` script to set the `USE_UNICORN=1` flag. If you have `/etc/default/gitlab`, then you should edit it instead. 1. Restart GitLab. ## Troubleshooting diff --git a/doc/user/group/roadmap/index.md b/doc/user/group/roadmap/index.md index 124aa217272..e603457b1a1 100644 --- a/doc/user/group/roadmap/index.md +++ b/doc/user/group/roadmap/index.md @@ -14,7 +14,7 @@ shows such a visualization for all the epics which are under a group and/or its > [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/5164) in GitLab 12.9. On the epic bars, you can see their title, progress, and completed weight percentage. -When you hover over an epic bar, a popover appears with its description, start and due dates, and weight completed. +When you hover over an epic bar, a popover appears with its title, start and due dates, and weight completed. ![roadmap view](img/roadmap_view_v12_9.png) diff --git a/lib/gitlab/checks/post_push_message.rb b/lib/gitlab/checks/post_push_message.rb index 492dbb5a596..b3c981d252b 100644 --- a/lib/gitlab/checks/post_push_message.rb +++ b/lib/gitlab/checks/post_push_message.rb @@ -3,8 +3,8 @@ module Gitlab module Checks class PostPushMessage - def initialize(project, user, protocol) - @project = project + def initialize(repository, user, protocol) + @repository = repository @user = user @protocol = protocol end @@ -34,14 +34,21 @@ module Gitlab protected - attr_reader :project, :user, :protocol + attr_reader :repository, :user, :protocol + + delegate :project, to: :repository, allow_nil: true + delegate :container, to: :repository, allow_nil: false def self.message_key(user_id, project_id) raise NotImplementedError end def url_to_repo - protocol == 'ssh' ? project.ssh_url_to_repo : project.http_url_to_repo + protocol == 'ssh' ? message_subject.ssh_url_to_repo : message_subject.http_url_to_repo + end + + def message_subject + repository.repo_type.wiki? ? project.wiki : container end end end diff --git a/lib/gitlab/checks/project_moved.rb b/lib/gitlab/checks/project_moved.rb index 6f04fddc6c4..4cc35de9c2d 100644 --- a/lib/gitlab/checks/project_moved.rb +++ b/lib/gitlab/checks/project_moved.rb @@ -5,10 +5,10 @@ module Gitlab class ProjectMoved < PostPushMessage REDIRECT_NAMESPACE = "redirect_namespace" - def initialize(project, user, protocol, redirected_path) + def initialize(repository, user, protocol, redirected_path) @redirected_path = redirected_path - super(project, user, protocol) + super(repository, user, protocol) end def message diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 7361ccf4aa2..c400e1cd4fd 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -188,7 +188,7 @@ module Gitlab def add_project_moved_message! return if redirected_path.nil? - project_moved = Checks::ProjectMoved.new(project, user, protocol, redirected_path) + project_moved = Checks::ProjectMoved.new(repository, user, protocol, redirected_path) project_moved.add_message end @@ -250,7 +250,7 @@ module Gitlab @project = project user_access.project = @project - Checks::ProjectCreated.new(project, user, protocol).add_message + Checks::ProjectCreated.new(repository, user, protocol).add_message end def check_repository_existence! diff --git a/lib/gitlab/git_access_snippet.rb b/lib/gitlab/git_access_snippet.rb index 87399f8d07f..e11c1ea527c 100644 --- a/lib/gitlab/git_access_snippet.rb +++ b/lib/gitlab/git_access_snippet.rb @@ -39,11 +39,11 @@ module Gitlab override :check_project! def check_project!(cmd, changes) - if snippet.is_a?(ProjectSnippet) - check_namespace! - check_project_accessibility! - # TODO add add_project_moved_message! to handle non-project repo https://gitlab.com/gitlab-org/gitlab/issues/205646 - end + return unless snippet.is_a?(ProjectSnippet) + + check_namespace! + check_project_accessibility! + add_project_moved_message! end override :check_push_access! diff --git a/lib/gitlab/repo_path.rb b/lib/gitlab/repo_path.rb index da74c38d0ec..67e23624045 100644 --- a/lib/gitlab/repo_path.rb +++ b/lib/gitlab/repo_path.rb @@ -19,8 +19,7 @@ module Gitlab # Removing the suffix (.wiki, .design, ...) from the project path full_path = repo_path.chomp(type.path_suffix) - container, project, was_redirected = find_container(type, full_path) - redirected_path = repo_path if was_redirected + container, project, redirected_path = find_container(type, full_path) return [container, project, type, redirected_path] if container end @@ -33,22 +32,23 @@ module Gitlab def self.find_container(type, full_path) if type.snippet? - snippet, was_redirected = find_snippet(full_path) + snippet, redirected_path = find_snippet(full_path) - [snippet, snippet&.project, was_redirected] + [snippet, snippet&.project, redirected_path] else - project, was_redirected = find_project(full_path) + project, redirected_path = find_project(full_path) - [project, project, was_redirected] + [project, project, redirected_path] end end def self.find_project(project_path) - return [nil, false] if project_path.blank? + return [nil, nil] if project_path.blank? project = Project.find_by_full_path(project_path, follow_redirects: true) + redirected_path = redirected?(project, project_path) ? project_path : nil - [project, redirected?(project, project_path)] + [project, redirected_path] end def self.redirected?(project, project_path) @@ -59,12 +59,12 @@ module Gitlab # - snippets/1 # - h5bp/html5-boilerplate/snippets/53 def self.find_snippet(snippet_path) - return [nil, false] if snippet_path.blank? + return [nil, nil] if snippet_path.blank? snippet_id, project_path = extract_snippet_info(snippet_path) - project, was_redirected = find_project(project_path) + project, redirected_path = find_project(project_path) - [Snippet.find_by_id_and_project(id: snippet_id, project: project), was_redirected] + [Snippet.find_by_id_and_project(id: snippet_id, project: project), redirected_path] end def self.extract_snippet_info(snippet_path) diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index 1c51288adf6..982c1dc8866 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -26,7 +26,7 @@ ### Environment variables RAILS_ENV="production" -EXPERIMENTAL_PUMA="" +USE_UNICORN="" # Script variable names should be lower-case not to conflict with # internal /bin/sh variables such as PATH, EDITOR or SHELL. @@ -68,10 +68,10 @@ if ! cd "$app_root" ; then fi # Select the web server to use -if [ -z "$EXPERIMENTAL_PUMA" ]; then - use_web_server="unicorn" -else +if [ -z "$USE_UNICORN" ]; then use_web_server="puma" +else + use_web_server="unicorn" fi diff --git a/lib/support/init.d/gitlab.default.example b/lib/support/init.d/gitlab.default.example index ab41dba3017..bb271b16836 100644 --- a/lib/support/init.d/gitlab.default.example +++ b/lib/support/init.d/gitlab.default.example @@ -5,8 +5,8 @@ # Normal values are "production", "test" and "development". RAILS_ENV="production" -# Uncomment the line below to enable Puma web server instead of Unicorn. -# EXPERIMENTAL_PUMA=1 +# Uncomment the line below to enable the Unicorn web server instead of Puma. +# USE_UNICORN=1 # app_user defines the user that GitLab is run as. # The default is "git". diff --git a/locale/gitlab.pot b/locale/gitlab.pot index a335ede2ea9..fd45ad4e521 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -16775,6 +16775,9 @@ msgstr "" msgid "Require users to prove ownership of custom domains" msgstr "" +msgid "Requirements" +msgstr "" + msgid "Requires approval from %{names}." msgid_plural "Requires %{count} more approvals from %{names}." msgstr[0] "" diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb index 10958db299b..2b8dfc4a5fa 100644 --- a/spec/features/projects/navbar_spec.rb +++ b/spec/features/projects/navbar_spec.rb @@ -18,6 +18,13 @@ describe 'Project navbar' do } end + let(:requirements_nav_item) do + { + nav_item: _('Requirements'), + nav_sub_items: [_('List')] + } + end + let(:structure) do [ { @@ -54,6 +61,7 @@ describe 'Project navbar' do nav_item: _('Merge Requests'), nav_sub_items: [] }, + (requirements_nav_item if Gitlab.ee?), { nav_item: _('CI / CD'), nav_sub_items: [ @@ -100,6 +108,7 @@ describe 'Project navbar' do end before do + stub_licensed_features(requirements: false) project.add_maintainer(user) sign_in(user) end @@ -123,5 +132,15 @@ describe 'Project navbar' do it_behaves_like 'verified navigation bar' end + + context 'when requirements is available' do + before do + stub_licensed_features(requirements: true) + + visit project_path(project) + end + + it_behaves_like 'verified navigation bar' + end end end diff --git a/spec/lib/gitlab/checks/project_created_spec.rb b/spec/lib/gitlab/checks/project_created_spec.rb index 373fef2a240..bbc97155374 100644 --- a/spec/lib/gitlab/checks/project_created_spec.rb +++ b/spec/lib/gitlab/checks/project_created_spec.rb @@ -3,24 +3,29 @@ require 'spec_helper' describe Gitlab::Checks::ProjectCreated, :clean_gitlab_redis_shared_state do - let(:user) { create(:user) } - let(:project) { create(:project) } + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :repository, namespace: user.namespace) } + let(:protocol) { 'http' } + let(:git_user) { user } + let(:repository) { project.repository } + + subject { described_class.new(repository, git_user, 'http') } describe '.fetch_message' do context 'with a project created message queue' do - let(:project_created) { described_class.new(project, user, 'http') } - before do - project_created.add_message + subject.add_message end it 'returns project created message' do - expect(described_class.fetch_message(user.id, project.id)).to eq(project_created.message) + expect(described_class.fetch_message(user.id, project.id)).to eq(subject.message) end it 'deletes the project created message from redis' do expect(Gitlab::Redis::SharedState.with { |redis| redis.get("project_created:#{user.id}:#{project.id}") }).not_to be_nil + described_class.fetch_message(user.id, project.id) + expect(Gitlab::Redis::SharedState.with { |redis| redis.get("project_created:#{user.id}:#{project.id}") }).to be_nil end end @@ -34,15 +39,15 @@ describe Gitlab::Checks::ProjectCreated, :clean_gitlab_redis_shared_state do describe '#add_message' do it 'queues a project created message' do - project_created = described_class.new(project, user, 'http') - - expect(project_created.add_message).to eq('OK') + expect(subject.add_message).to eq('OK') end - it 'handles anonymous push' do - project_created = described_class.new(nil, user, 'http') + context 'when user is nil' do + let(:git_user) { nil } - expect(project_created.add_message).to be_nil + it 'handles anonymous push' do + expect(subject.add_message).to be_nil + end end end end diff --git a/spec/lib/gitlab/checks/project_moved_spec.rb b/spec/lib/gitlab/checks/project_moved_spec.rb index 3de397760b4..1d1d6211088 100644 --- a/spec/lib/gitlab/checks/project_moved_spec.rb +++ b/spec/lib/gitlab/checks/project_moved_spec.rb @@ -3,24 +3,30 @@ require 'spec_helper' describe Gitlab::Checks::ProjectMoved, :clean_gitlab_redis_shared_state do - let(:user) { create(:user) } - let(:project) { create(:project) } + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :repository, :wiki_repo, namespace: user.namespace) } + let(:repository) { project.repository } + let(:protocol) { 'http' } + let(:git_user) { user } + let(:redirect_path) { 'foo/bar' } + + subject { described_class.new(repository, git_user, protocol, redirect_path) } describe '.fetch_message' do context 'with a redirect message queue' do - it 'returns the redirect message' do - project_moved = described_class.new(project, user, 'http', 'foo/bar') - project_moved.add_message + before do + subject.add_message + end - expect(described_class.fetch_message(user.id, project.id)).to eq(project_moved.message) + it 'returns the redirect message' do + expect(described_class.fetch_message(user.id, project.id)).to eq(subject.message) end it 'deletes the redirect message from redis' do - project_moved = described_class.new(project, user, 'http', 'foo/bar') - project_moved.add_message - expect(Gitlab::Redis::SharedState.with { |redis| redis.get("redirect_namespace:#{user.id}:#{project.id}") }).not_to be_nil + described_class.fetch_message(user.id, project.id) + expect(Gitlab::Redis::SharedState.with { |redis| redis.get("redirect_namespace:#{user.id}:#{project.id}") }).to be_nil end end @@ -34,29 +40,82 @@ describe Gitlab::Checks::ProjectMoved, :clean_gitlab_redis_shared_state do describe '#add_message' do it 'queues a redirect message' do - project_moved = described_class.new(project, user, 'http', 'foo/bar') - expect(project_moved.add_message).to eq("OK") + expect(subject.add_message).to eq("OK") end - it 'handles anonymous clones' do - project_moved = described_class.new(project, nil, 'http', 'foo/bar') + context 'when user is nil' do + let(:git_user) { nil } - expect(project_moved.add_message).to eq(nil) + it 'handles anonymous clones' do + expect(subject.add_message).to be_nil + end end end describe '#message' do - it 'returns a redirect message' do - project_moved = described_class.new(project, user, 'http', 'foo/bar') - message = <<~MSG - Project 'foo/bar' was moved to '#{project.full_path}'. + shared_examples 'errors per protocol' do + shared_examples 'returns redirect message' do + it do + message = <<~MSG + Project '#{redirect_path}' was moved to '#{project.full_path}'. + + Please update your Git remote: + + git remote set-url origin #{url_to_repo} + MSG + + expect(subject.message).to eq(message) + end + end + + context 'when protocol is http' do + it_behaves_like 'returns redirect message' do + let(:url_to_repo) { http_url_to_repo } + end + end + + context 'when protocol is ssh' do + let(:protocol) { 'ssh' } - Please update your Git remote: + it_behaves_like 'returns redirect message' do + let(:url_to_repo) { ssh_url_to_repo } + end + end + end + + context 'with project' do + it_behaves_like 'errors per protocol' do + let(:http_url_to_repo) { project.http_url_to_repo } + let(:ssh_url_to_repo) { project.ssh_url_to_repo } + end + end + + context 'with wiki' do + let(:repository) { project.wiki.repository } - git remote set-url origin #{project.http_url_to_repo} - MSG + it_behaves_like 'errors per protocol' do + let(:http_url_to_repo) { project.wiki.http_url_to_repo } + let(:ssh_url_to_repo) { project.wiki.ssh_url_to_repo } + end + end - expect(project_moved.message).to eq(message) + context 'with project snippet' do + let_it_be(:snippet) { create(:project_snippet, :repository, project: project, author: user) } + let(:repository) { snippet.repository } + + it_behaves_like 'errors per protocol' do + let(:http_url_to_repo) { snippet.http_url_to_repo } + let(:ssh_url_to_repo) { snippet.ssh_url_to_repo } + end + end + + context 'with personal snippet' do + let_it_be(:snippet) { create(:personal_snippet, :repository, author: user) } + let(:repository) { snippet.repository } + + it 'returns nil' do + expect(subject.add_message).to be_nil + end end end end diff --git a/spec/lib/gitlab/repo_path_spec.rb b/spec/lib/gitlab/repo_path_spec.rb index e72bdc01940..68571b9de20 100644 --- a/spec/lib/gitlab/repo_path_spec.rb +++ b/spec/lib/gitlab/repo_path_spec.rb @@ -8,7 +8,8 @@ describe ::Gitlab::RepoPath do let_it_be(:project) { create(:project, :repository) } let_it_be(:personal_snippet) { create(:personal_snippet) } let_it_be(:project_snippet) { create(:project_snippet, project: project) } - let_it_be(:redirect) { project.route.create_redirect('foo/bar/baz') } + let_it_be(:redirect_route) { 'foo/bar/baz' } + let_it_be(:redirect) { project.route.create_redirect(redirect_route) } describe '.parse' do context 'a repository storage path' do @@ -43,22 +44,20 @@ describe ::Gitlab::RepoPath do end context 'of a redirected project' do - let(:redirect) { project.route.create_redirect('foo/bar') } - it 'parses a relative repository path' do - expect(described_class.parse(redirect.path + '.git')).to eq([project, project, Gitlab::GlRepository::PROJECT, 'foo/bar']) + expect(described_class.parse(redirect.path + '.git')).to eq([project, project, Gitlab::GlRepository::PROJECT, redirect_route]) end it 'parses a relative wiki path' do - expect(described_class.parse(redirect.path + '.wiki.git')).to eq([project, project, Gitlab::GlRepository::WIKI, 'foo/bar.wiki']) + expect(described_class.parse(redirect.path + '.wiki.git')).to eq([project, project, Gitlab::GlRepository::WIKI, redirect_route]) end it 'parses a relative path starting with /' do - expect(described_class.parse('/' + redirect.path + '.git')).to eq([project, project, Gitlab::GlRepository::PROJECT, 'foo/bar']) + expect(described_class.parse('/' + redirect.path + '.git')).to eq([project, project, Gitlab::GlRepository::PROJECT, redirect_route]) end it 'parses a redirected project snippet repository path' do - expect(described_class.parse(redirect.path + "/snippets/#{project_snippet.id}.git")).to eq([project_snippet, project, Gitlab::GlRepository::SNIPPET, "foo/bar/snippets/#{project_snippet.id}"]) + expect(described_class.parse(redirect.path + "/snippets/#{project_snippet.id}.git")).to eq([project_snippet, project, Gitlab::GlRepository::SNIPPET, redirect_route]) end end end @@ -71,8 +70,8 @@ describe ::Gitlab::RepoPath do describe '.find_project' do context 'when finding a project by its canonical path' do context 'when the cases match' do - it 'returns the project and false' do - expect(described_class.find_project(project.full_path)).to eq([project, false]) + it 'returns the project and nil' do + expect(described_class.find_project(project.full_path)).to eq([project, nil]) end end @@ -81,45 +80,45 @@ describe ::Gitlab::RepoPath do # easy and safe to redirect someone to the correctly-cased URL. For git # requests, we should accept wrongly-cased URLs because it is a pain to # block people's git operations and force them to update remote URLs. - it 'returns the project and false' do - expect(described_class.find_project(project.full_path.upcase)).to eq([project, false]) + it 'returns the project and nil' do + expect(described_class.find_project(project.full_path.upcase)).to eq([project, nil]) end end end context 'when finding a project via a redirect' do - it 'returns the project and true' do - expect(described_class.find_project(redirect.path)).to eq([project, true]) + it 'returns the project and nil' do + expect(described_class.find_project(redirect.path)).to eq([project, redirect.path]) end end end describe '.find_snippet' do it 'extracts path and id from personal snippet route' do - expect(described_class.find_snippet("snippets/#{personal_snippet.id}")).to eq([personal_snippet, false]) + expect(described_class.find_snippet("snippets/#{personal_snippet.id}")).to eq([personal_snippet, nil]) end it 'extracts path and id from project snippet route' do - expect(described_class.find_snippet("#{project.full_path}/snippets/#{project_snippet.id}")).to eq([project_snippet, false]) + expect(described_class.find_snippet("#{project.full_path}/snippets/#{project_snippet.id}")).to eq([project_snippet, nil]) end it 'returns nil for invalid snippet paths' do aggregate_failures do - expect(described_class.find_snippet("snippets/#{project_snippet.id}")).to eq([nil, false]) - expect(described_class.find_snippet("#{project.full_path}/snippets/#{personal_snippet.id}")).to eq([nil, false]) - expect(described_class.find_snippet('')).to eq([nil, false]) + expect(described_class.find_snippet("snippets/#{project_snippet.id}")).to eq([nil, nil]) + expect(described_class.find_snippet("#{project.full_path}/snippets/#{personal_snippet.id}")).to eq([nil, nil]) + expect(described_class.find_snippet('')).to eq([nil, nil]) end end it 'returns nil for snippets not associated with the project' do snippet = create(:project_snippet) - expect(described_class.find_snippet("#{project.full_path}/snippets/#{snippet.id}")).to eq([nil, false]) + expect(described_class.find_snippet("#{project.full_path}/snippets/#{snippet.id}")).to eq([nil, nil]) end context 'when finding a project snippet via a redirect' do it 'returns the project and true' do - expect(described_class.find_snippet("#{redirect.path}/snippets/#{project_snippet.id}")).to eq([project_snippet, true]) + expect(described_class.find_snippet("#{redirect.path}/snippets/#{project_snippet.id}")).to eq([project_snippet, redirect.path]) end end end diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb index c9656b4d6ca..7ae4a81ddd7 100644 --- a/spec/models/snippet_spec.rb +++ b/spec/models/snippet_spec.rb @@ -697,4 +697,20 @@ describe Snippet do it { is_expected.to eq result } end end + + describe '#url_to_repo' do + subject { snippet.url_to_repo } + + context 'with personal snippet' do + let(:snippet) { create(:personal_snippet) } + + it { is_expected.to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + "snippets/#{snippet.id}.git") } + end + + context 'with project snippet' do + let(:snippet) { create(:project_snippet) } + + it { is_expected.to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + "#{snippet.project.full_path}/snippets/#{snippet.id}.git") } + end + end end diff --git a/spec/services/post_receive_service_spec.rb b/spec/services/post_receive_service_spec.rb index f3631ff922f..b4f48696b15 100644 --- a/spec/services/post_receive_service_spec.rb +++ b/spec/services/post_receive_service_spec.rb @@ -234,7 +234,7 @@ describe PostReceiveService do context 'with a redirected data' do it 'returns redirected message on the response' do - project_moved = Gitlab::Checks::ProjectMoved.new(project, user, 'http', 'foo/baz') + project_moved = Gitlab::Checks::ProjectMoved.new(project.repository, user, 'http', 'foo/baz') project_moved.add_message expect(subject).to include(build_basic_message(project_moved.message)) @@ -243,7 +243,7 @@ describe PostReceiveService do context 'with new project data' do it 'returns new project message on the response' do - project_created = Gitlab::Checks::ProjectCreated.new(project, user, 'http') + project_created = Gitlab::Checks::ProjectCreated.new(project.repository, user, 'http') project_created.add_message expect(subject).to include(build_basic_message(project_created.message)) diff --git a/spec/support/shared_examples/workers/idempotency_shared_examples.rb b/spec/support/shared_examples/workers/idempotency_shared_examples.rb index 19be1fe2c9d..9d9b371d61a 100644 --- a/spec/support/shared_examples/workers/idempotency_shared_examples.rb +++ b/spec/support/shared_examples/workers/idempotency_shared_examples.rb @@ -16,6 +16,8 @@ # end # RSpec.shared_examples 'an idempotent worker' do + let(:worker_exec_times) { IdempotentWorkerHelper::WORKER_EXEC_TIMES } + # Avoid stubbing calls for a more accurate run. subject do defined?(job_args) ? perform_multiple(job_args) : perform_multiple diff --git a/spec/workers/concerns/application_worker_spec.rb b/spec/workers/concerns/application_worker_spec.rb index ae5244e2f62..2fbaaf1131f 100644 --- a/spec/workers/concerns/application_worker_spec.rb +++ b/spec/workers/concerns/application_worker_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe ApplicationWorker do - let(:worker) do + let_it_be(:worker) do Class.new do def self.name 'Gitlab::Foo::Bar::DummyWorker' @@ -13,12 +13,51 @@ describe ApplicationWorker do end end + let(:instance) { worker.new } + describe 'Sidekiq options' do it 'sets the queue name based on the class name' do expect(worker.sidekiq_options['queue']).to eq('foo_bar_dummy') end end + describe '#structured_payload' do + let(:payload) { {} } + + subject(:result) { instance.structured_payload(payload) } + + it 'adds worker related payload' do + instance.jid = 'a jid' + + expect(result).to include( + 'class' => worker.class, + 'job_status' => 'running', + 'queue' => worker.queue, + 'jid' => instance.jid + ) + end + + it 'adds labkit context' do + user = build_stubbed(:user, username: 'jane-doe') + + instance.with_context(user: user) do + expect(result).to include('meta.user' => user.username) + end + end + + it 'adds custom payload converting stringified keys' do + payload[:message] = 'some message' + + expect(result).to include('message' => payload[:message]) + end + + it 'does not override predefined context keys with custom payload' do + payload['class'] = 'custom value' + + expect(result).to include('class' => worker.class) + end + end + describe '.queue_namespace' do it 'sets the queue name based on the class name' do worker.queue_namespace :some_namespace diff --git a/spec/workers/expire_job_cache_worker_spec.rb b/spec/workers/expire_job_cache_worker_spec.rb index 797f110ec68..2776624f14c 100644 --- a/spec/workers/expire_job_cache_worker_spec.rb +++ b/spec/workers/expire_job_cache_worker_spec.rb @@ -21,12 +21,12 @@ describe ExpireJobCacheWorker do allow(Gitlab::EtagCaching::Store).to receive(:new) { spy_store } expect(spy_store).to receive(:touch) - .exactly(IdempotentWorkerHelper::WORKER_EXEC_TIMES).times + .exactly(worker_exec_times).times .with(pipeline_path) .and_call_original expect(spy_store).to receive(:touch) - .exactly(IdempotentWorkerHelper::WORKER_EXEC_TIMES).times + .exactly(worker_exec_times).times .with(job_path) .and_call_original |