From 739029bb0f03ff2bf70d67b3d2a09ddd196143a6 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 4 May 2018 12:40:37 +0200 Subject: Fix API to remove deploy key from project instead of deleting it entirely --- .../unreleased/security-dm-delete-deploy-key.yml | 5 +++ lib/api/deploy_keys.rb | 6 ++-- spec/requests/api/deploy_keys_spec.rb | 40 +++++++++++++++++++++- 3 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 changelogs/unreleased/security-dm-delete-deploy-key.yml diff --git a/changelogs/unreleased/security-dm-delete-deploy-key.yml b/changelogs/unreleased/security-dm-delete-deploy-key.yml new file mode 100644 index 00000000000..aa94e7b6072 --- /dev/null +++ b/changelogs/unreleased/security-dm-delete-deploy-key.yml @@ -0,0 +1,5 @@ +--- +title: Fix API to remove deploy key from project instead of deleting it entirely +merge_request: +author: +type: security diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb index 70d43ac1d79..b7aadc27e71 100644 --- a/lib/api/deploy_keys.rb +++ b/lib/api/deploy_keys.rb @@ -148,10 +148,10 @@ module API requires :key_id, type: Integer, desc: 'The ID of the deploy key' end delete ":id/deploy_keys/:key_id" do - key = user_project.deploy_keys.find(params[:key_id]) - not_found!('Deploy Key') unless key + deploy_key_project = user_project.deploy_keys_projects.find_by(deploy_key_id: params[:key_id]) + not_found!('Deploy Key') unless deploy_key_project - destroy_conditionally!(key) + destroy_conditionally!(deploy_key_project) end end end diff --git a/spec/requests/api/deploy_keys_spec.rb b/spec/requests/api/deploy_keys_spec.rb index ae9c0e9c304..32fc704a79b 100644 --- a/spec/requests/api/deploy_keys_spec.rb +++ b/spec/requests/api/deploy_keys_spec.rb @@ -171,7 +171,7 @@ describe API::DeployKeys do deploy_key end - it 'deletes existing key' do + it 'removes existing key from project' do expect do delete api("/projects/#{project.id}/deploy_keys/#{deploy_key.id}", admin) @@ -179,6 +179,44 @@ describe API::DeployKeys do end.to change { project.deploy_keys.count }.by(-1) end + context 'when the deploy key is public' do + it 'does not delete the deploy key' do + expect do + delete api("/projects/#{project.id}/deploy_keys/#{deploy_key.id}", admin) + + expect(response).to have_gitlab_http_status(204) + end.not_to change { DeployKey.count } + end + end + + context 'when the deploy key is not public' do + let!(:deploy_key) { create(:deploy_key, public: false) } + + context 'when the deploy key is only used by this project' do + it 'deletes the deploy key' do + expect do + delete api("/projects/#{project.id}/deploy_keys/#{deploy_key.id}", admin) + + expect(response).to have_gitlab_http_status(204) + end.to change { DeployKey.count }.by(-1) + end + end + + context 'when the deploy key is used by other projects' do + before do + create(:deploy_keys_project, project: project2, deploy_key: deploy_key) + end + + it 'does not delete the deploy key' do + expect do + delete api("/projects/#{project.id}/deploy_keys/#{deploy_key.id}", admin) + + expect(response).to have_gitlab_http_status(204) + end.not_to change { DeployKey.count } + end + end + end + it 'returns 404 Not Found with invalid ID' do delete api("/projects/#{project.id}/deploy_keys/404", admin) -- cgit v1.2.1 From 8417f74f23a75020a14f39d939c4dd1cc5419d07 Mon Sep 17 00:00:00 2001 From: Tiago Botelho Date: Fri, 4 May 2018 19:24:55 +0200 Subject: Remove password and password_confirmation from whitelisted params in ProfilesController to prevent password from being changed without previous password being provided --- app/controllers/profiles_controller.rb | 2 -- ...ate-their-password-without-entering-current-password.yml | 5 +++++ spec/controllers/profiles_controller_spec.rb | 13 +++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 changelogs/unreleased/security-users-can-update-their-password-without-entering-current-password.yml diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index ac71f72e624..9f5ad23a20f 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -93,8 +93,6 @@ class ProfilesController < Profiles::ApplicationController :linkedin, :location, :name, - :password, - :password_confirmation, :public_email, :skype, :twitter, diff --git a/changelogs/unreleased/security-users-can-update-their-password-without-entering-current-password.yml b/changelogs/unreleased/security-users-can-update-their-password-without-entering-current-password.yml new file mode 100644 index 00000000000..824fbd41ab8 --- /dev/null +++ b/changelogs/unreleased/security-users-can-update-their-password-without-entering-current-password.yml @@ -0,0 +1,5 @@ +--- +title: Prevent user passwords from being changed without providing the previous password +merge_request: +author: +type: security diff --git a/spec/controllers/profiles_controller_spec.rb b/spec/controllers/profiles_controller_spec.rb index c621eb69171..4530a301d4d 100644 --- a/spec/controllers/profiles_controller_spec.rb +++ b/spec/controllers/profiles_controller_spec.rb @@ -3,6 +3,19 @@ require('spec_helper') describe ProfilesController, :request_store do let(:user) { create(:user) } + describe 'POST update' do + it 'does not update password' do + sign_in(user) + + expect do + post :update, + user: { password: 'hello12345', password_confirmation: 'hello12345' } + end.not_to change { user.reload.encrypted_password } + + expect(response.status).to eq(302) + end + end + describe 'PUT update' do it 'allows an email update from a user without an external email address' do sign_in(user) -- cgit v1.2.1 From 2ac407b8d4a3f076a4c4ebbb8151b869b8220e15 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 9 May 2018 09:04:06 +0200 Subject: Deprecate the Kubernetes service docs --- doc/administration/integration/terminal.md | 16 ++- doc/ci/autodeploy/index.md | 130 +------------------ doc/ci/environments.md | 7 +- doc/ci/variables/README.md | 4 +- .../integrations/img/kubernetes_configuration.png | Bin 14407 -> 0 bytes doc/user/project/integrations/kubernetes.md | 138 +-------------------- doc/user/project/integrations/project_services.md | 1 - 7 files changed, 14 insertions(+), 282 deletions(-) delete mode 100644 doc/user/project/integrations/img/kubernetes_configuration.png diff --git a/doc/administration/integration/terminal.md b/doc/administration/integration/terminal.md index 91e844c7b42..32ad63c3706 100644 --- a/doc/administration/integration/terminal.md +++ b/doc/administration/integration/terminal.md @@ -1,12 +1,13 @@ # Web terminals -> [Introduced][ce-7690] in GitLab 8.15. Only project masters and owners can - access web terminals. +> +[Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7690) +in GitLab 8.15. Only project masters and owners can access web terminals. -With the introduction of the [Kubernetes project service][kubservice], GitLab -gained the ability to store and use credentials for a Kubernetes cluster. One -of the things it uses these credentials for is providing access to -[web terminals](../../ci/environments.html#web-terminals) for environments. +With the introduction of the [Kubernetes integration](../../user/project/clusters/index.md), +GitLab gained the ability to store and use credentials for a Kubernetes cluster. +One of the things it uses these credentials for is providing access to +[web terminals](../../ci/environments.md#web-terminals) for environments. ## How it works @@ -80,6 +81,3 @@ Terminal sessions use long-lived connections; by default, these may last forever. You can configure a maximum session time in the Admin area of your GitLab instance if you find this undesirable from a scalability or security point of view. - -[ce-7690]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7690 -[kubservice]: ../../user/project/integrations/kubernetes.md diff --git a/doc/ci/autodeploy/index.md b/doc/ci/autodeploy/index.md index 7102af5c529..985ec4b972c 100644 --- a/doc/ci/autodeploy/index.md +++ b/doc/ci/autodeploy/index.md @@ -1,129 +1 @@ -# Auto Deploy - -> [Introduced][mr-8135] in GitLab 8.15. -> Auto deploy is an experimental feature and is **not recommended for Production use** at this time. - -> As of GitLab 9.1, access to the container registry is only available while the -Pipeline is running. Restarting a pod, scaling a service, or other actions which -require on-going access **will fail**. On-going secure access is planned for a -subsequent release. - -> As of GitLab 10.0, Auto Deploy templates are **deprecated** and the -functionality has been included in [Auto -DevOps](../../topics/autodevops/index.md). - -Auto deploy is an easy way to configure GitLab CI for the deployment of your -application. GitLab Community maintains a list of `.gitlab-ci.yml` -templates for various infrastructure providers and deployment scripts -powering them. These scripts are responsible for packaging your application, -setting up the infrastructure and spinning up necessary services (for -example a database). - -## How it works - -The Autodeploy templates are based on the [kubernetes-deploy][kube-deploy] -project which is used to simplify the deployment process to Kubernetes by -providing intelligent `build`, `deploy`, and `destroy` commands which you can -use in your `.gitlab-ci.yml` as is. It uses [Herokuish](https://github.com/gliderlabs/herokuish), -which uses [Heroku buildpacks](https://devcenter.heroku.com/articles/buildpacks) -to do some of the work, plus some of GitLab's own tools to package it all up. For -your convenience, a [Docker image][kube-image] is also provided. - -You can use the [Kubernetes project service](../../user/project/integrations/kubernetes.md) -to store credentials to your infrastructure provider and they will be available -during the deployment. - -## Quick start - -We made a [simple guide](quick_start_guide.md) to using Auto Deploy with GitLab.com. - -For a demonstration of GitLab Auto Deploy, read the blog post [Auto Deploy from GitLab to an OpenShift Container Cluster](https://about.gitlab.com/2017/05/16/devops-containers-gitlab-openshift/) - -## Supported templates - -The list of supported auto deploy templates is available in the -[gitlab-ci-yml project][auto-deploy-templates]. - -## Configuration - ->**Note:** -In order to understand why the following steps are required, read the -[how it works](#how-it-works) section. - -To configure Autodeploy, you will need to: - -1. Enable a deployment [project service][project-services] to store your - credentials. For example, if you want to deploy to OpenShift you have to - enable [Kubernetes service][kubernetes-service]. -1. Configure GitLab Runner to use the - [Docker or Kubernetes executor](https://docs.gitlab.com/runner/executors/) with - [privileged mode enabled][docker-in-docker]. -1. Navigate to the "Project" tab and click "Set up auto deploy" button. - ![Auto deploy button](img/auto_deploy_button.png) -1. Select a template. - ![Dropdown with auto deploy templates](img/auto_deploy_dropdown.png) -1. Commit your changes and create a merge request. -1. Test your deployment configuration using a [Review App][review-app] that was - created automatically for you. - -## Private project support - -> Experimental support [introduced][mr-2] in GitLab 9.1. - -When a project has been marked as private, GitLab's [Container Registry][container-registry] requires authentication when downloading containers. Auto deploy will automatically provide the required authentication information to Kubernetes, allowing temporary access to the registry. Authentication credentials will be valid while the pipeline is running, allowing for a successful initial deployment. - -After the pipeline completes, Kubernetes will no longer be able to access the container registry. Restarting a pod, scaling a service, or other actions which require on-going access to the registry will fail. On-going secure access is planned for a subsequent release. - -## PostgreSQL database support - -> Experimental support [introduced][mr-8] in GitLab 9.1. - -In order to support applications that require a database, [PostgreSQL][postgresql] is provisioned by default. Credentials to access the database are preconfigured, but can be customized by setting the associated [variables](#postgresql-variables). These credentials can be used for defining a `DATABASE_URL` of the format: `postgres://user:password@postgres-host:postgres-port/postgres-database`. It is important to note that the database itself is temporary, and contents will be not be saved. - -PostgreSQL provisioning can be disabled by setting the variable `DISABLE_POSTGRES` to `"yes"`. - -The following PostgreSQL variables are supported: - -1. `DISABLE_POSTGRES: "yes"`: disable automatic deployment of PostgreSQL -1. `POSTGRES_USER: "my-user"`: use custom username for PostgreSQL -1. `POSTGRES_PASSWORD: "password"`: use custom password for PostgreSQL -1. `POSTGRES_DB: "my database"`: use custom database name for PostgreSQL - -## Auto Monitoring - -> Introduced in [GitLab 9.5](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/13438). - -Apps auto-deployed using one the [Kubernetes templates](#supported-templates) can also be automatically monitored for: - -* Response Metrics: latency, throughput, error rate -* System Metrics: CPU utilization, memory utilization - -Metrics are gathered from [nginx-ingress](../../user/project/integrations/prometheus_library/nginx_ingress.md) and [Kubernetes](../../user/project/integrations/prometheus_library/kubernetes.md). - -To view the metrics, open the [Monitoring dashboard for a deployed environment](../environments.md#monitoring-environments). - -![Auto Metrics](img/auto_monitoring.png) - -### Configuring Auto Monitoring - -If GitLab has been deployed using the [omnibus-gitlab](../../install/kubernetes/gitlab_omnibus.md) Helm chart, no configuration is required. - -If you have installed GitLab using a different method: - -1. [Deploy Prometheus](../../user/project/integrations/prometheus.md#configuring-your-own-prometheus-server-within-kubernetes) into your Kubernetes cluster -1. If you would like response metrics, ensure you are running at least version 0.9.0 of NGINX Ingress and [enable Prometheus metrics](https://github.com/kubernetes/ingress/blob/master/examples/customization/custom-vts-metrics/nginx/nginx-vts-metrics-conf.yaml). -1. Finally, [annotate](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) the NGINX Ingress deployment to be scraped by Prometheus using `prometheus.io/scrape: "true"` and `prometheus.io/port: "10254"`. - -[mr-8135]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8135 -[mr-2]: https://gitlab.com/gitlab-examples/kubernetes-deploy/merge_requests/2 -[mr-8]: https://gitlab.com/gitlab-examples/kubernetes-deploy/merge_requests/8 -[project-settings]: https://docs.gitlab.com/ce/public_access/public_access.html -[project-services]: ../../user/project/integrations/project_services.md -[auto-deploy-templates]: https://gitlab.com/gitlab-org/gitlab-ci-yml/tree/master/autodeploy -[kubernetes-service]: ../../user/project/integrations/kubernetes.md -[docker-in-docker]: ../docker/using_docker_build.md#use-docker-in-docker-executor -[review-app]: ../review_apps/index.md -[kube-image]: https://gitlab.com/gitlab-examples/kubernetes-deploy/container_registry "Kubernetes deploy Container Registry" -[kube-deploy]: https://gitlab.com/gitlab-examples/kubernetes-deploy "Kubernetes deploy example project" -[container-registry]: https://docs.gitlab.com/ce/user/project/container_registry.html -[postgresql]: https://www.postgresql.org/ +This document was moved to [another location](../../topics/autodevops/index.md#auto-deploy). diff --git a/doc/ci/environments.md b/doc/ci/environments.md index 517e25f00f7..526a194856b 100644 --- a/doc/ci/environments.md +++ b/doc/ci/environments.md @@ -24,7 +24,7 @@ Environments are like tags for your CI jobs, describing where code gets deployed Deployments are created when [jobs] deploy versions of code to environments, so every environment can have one or more deployments. GitLab keeps track of your deployments, so you always know what is currently being deployed on your -servers. If you have a deployment service such as [Kubernetes][kubernetes-service] +servers. If you have a deployment service such as [Kubernetes][kube] enabled for your project, you can use it to assist with your deployments, and can even access a [web terminal](#web-terminals) for your environment from within GitLab! @@ -604,7 +604,7 @@ Web terminals were added in GitLab 8.15 and are only available to project masters and owners. If you deploy to your environments with the help of a deployment service (e.g., -the [Kubernetes service][kubernetes-service]), GitLab can open +the [Kubernetes integration][kube]), GitLab can open a terminal session to your environment! This is a very powerful feature that allows you to debug issues without leaving the comfort of your web browser. To enable it, just follow the instructions given in the service integration @@ -670,7 +670,6 @@ Below are some links you may find interesting: [Pipelines]: pipelines.md [jobs]: yaml/README.md#jobs [yaml]: yaml/README.md -[kubernetes-service]: ../user/project/integrations/kubernetes.md [environments]: #environments [deployments]: #deployments [permissions]: ../user/permissions.md @@ -682,5 +681,5 @@ Below are some links you may find interesting: [gitlab-flow]: ../workflow/gitlab_flow.md [gitlab runner]: https://docs.gitlab.com/runner/ [git-strategy]: yaml/README.md#git-strategy -[kube]: ../user/project/integrations/kubernetes.md +[kube]: ../user/project/clusters/index.md [prom]: ../user/project/integrations/prometheus.md diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index 42367bf13f7..8489a91e7f3 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -215,8 +215,8 @@ are set in the build environment. These variables are only defined for [deployment jobs](../environments.md). Please consult the documentation of the project services that you are using to learn which variables they define. -An example project service that defines deployment variables is -[Kubernetes Service](../../user/project/integrations/kubernetes.md#deployment-variables). +An example project service that defines deployment variables is the +[Kubernetes integration](../../user/project/clusters/index.md#deployment-variables). ## Debug tracing diff --git a/doc/user/project/integrations/img/kubernetes_configuration.png b/doc/user/project/integrations/img/kubernetes_configuration.png deleted file mode 100644 index e535e2b8d46..00000000000 Binary files a/doc/user/project/integrations/img/kubernetes_configuration.png and /dev/null differ diff --git a/doc/user/project/integrations/kubernetes.md b/doc/user/project/integrations/kubernetes.md index f502d1c9821..9342a2cbb00 100644 --- a/doc/user/project/integrations/kubernetes.md +++ b/doc/user/project/integrations/kubernetes.md @@ -1,137 +1 @@ ---- -last_updated: 2017-12-28 ---- - -# GitLab Kubernetes / OpenShift integration - -CAUTION: **Warning:** -The Kubernetes service integration has been deprecated in GitLab 10.3. If the -service is active, the cluster information will still be editable, however we -advise to disable and reconfigure the clusters using the new -[Clusters](../clusters/index.md) page. If the service is inactive, the fields -will not be editable. Read [GitLab 10.3 release post](https://about.gitlab.com/2017/12/22/gitlab-10-3-released/#kubernetes-integration-service) for more information. - -GitLab can be configured to interact with Kubernetes, or other systems using the -Kubernetes API (such as OpenShift). - -Each project can be configured to connect to a different Kubernetes cluster, see -the [configuration](#configuration) section. - -## Configuration - -Navigate to the [Integrations page](project_services.md#accessing-the-project-services) -of your project and select the **Kubernetes** service to configure it. Fill in -all the needed parameters, check the "Active" checkbox and hit **Save changes** -for the changes to take effect. - -![Kubernetes configuration settings](img/kubernetes_configuration.png) - -The Kubernetes service takes the following parameters: - -- **API URL** - - It's the URL that GitLab uses to access the Kubernetes API. Kubernetes - exposes several APIs, we want the "base" URL that is common to all of them, - e.g., `https://kubernetes.example.com` rather than `https://kubernetes.example.com/api/v1`. -- **CA certificate** (optional) - - If the API is using a self-signed TLS certificate, you'll also need to include - the `ca.crt` contents here. -- **Project namespace** (optional) - The following apply: - - By default you don't have to fill it in; by leaving it blank, GitLab will - create one for you. - - Each project should have a unique namespace. - - The project namespace is not necessarily the namespace of the secret, if - you're using a secret with broader permissions, like the secret from `default`. - - You should **not** use `default` as the project namespace. - - If you or someone created a secret specifically for the project, usually - with limited permissions, the secret's namespace and project namespace may - be the same. -- **Token** - - GitLab authenticates against Kubernetes using service tokens, which are - scoped to a particular `namespace`. If you don't have a service token yet, - you can follow the - [Kubernetes documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) - to create one. You can also view or create service tokens in the - [Kubernetes dashboard](https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#config) - (under **Config > Secrets**). - -TIP: **Tip:** -If you have a single cluster that you want to use for all your projects, -you can pre-fill the settings page with a default template. To configure the -template, see [Services Templates](services_templates.md). - -## Deployment variables - -The Kubernetes service exposes the following -[deployment variables](../../../ci/variables/README.md#deployment-variables) in the -GitLab CI/CD build environment: - -- `KUBE_URL` - Equal to the API URL. -- `KUBE_TOKEN` - The Kubernetes token. -- `KUBE_NAMESPACE` - The Kubernetes namespace is auto-generated if not specified. - The default value is `-`. You can overwrite it to - use different one if needed, otherwise the `KUBE_NAMESPACE` variable will - receive the default value. -- `KUBE_CA_PEM_FILE` - Only present if a custom CA bundle was specified. Path - to a file containing PEM data. -- `KUBE_CA_PEM` (deprecated) - Only if a custom CA bundle was specified. Raw PEM data. -- `KUBECONFIG` - Path to a file containing `kubeconfig` for this deployment. - CA bundle would be embedded if specified. - -## What you can get with the Kubernetes integration - -Here's what you can do with GitLab if you enable the Kubernetes integration. - -### Deploy Boards - -> Available in [GitLab Premium][ee]. - -GitLab's Deploy Boards offer a consolidated view of the current health and -status of each CI [environment](../../../ci/environments.md) running on Kubernetes, -displaying the status of the pods in the deployment. Developers and other -teammates can view the progress and status of a rollout, pod by pod, in the -workflow they already use without any need to access Kubernetes. - -[> Read more about Deploy Boards](https://docs.gitlab.com/ee/user/project/deploy_boards.html) - -### Canary Deployments - -> Available in [GitLab Premium][ee]. - -Leverage [Kubernetes' Canary deployments](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments) -and visualize your canary deployments right inside the Deploy Board, without -the need to leave GitLab. - -[> Read more about Canary Deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html) - -### Kubernetes monitoring - -Automatically detect and monitor Kubernetes metrics. Automatic monitoring of -[NGINX ingress](./prometheus_library/nginx.md) is also supported. - -[> Read more about Kubernetes monitoring](prometheus_library/kubernetes.md) - -### Auto DevOps - -Auto DevOps automatically detects, builds, tests, deploys, and monitors your -applications. - -To make full use of Auto DevOps(Auto Deploy, Auto Review Apps, and Auto Monitoring) -you will need the Kubernetes project integration enabled. - -[> Read more about Auto DevOps](../../../topics/autodevops/index.md) - -### Web terminals - -NOTE: **Note:** -Introduced in GitLab 8.15. You must be the project owner or have `master` permissions -to use terminals. Support is limited to the first container in the -first pod of your environment. - -When enabled, the Kubernetes service adds [web terminal](../../../ci/environments.md#web-terminals) -support to your [environments](../../../ci/environments.md). This is based on the `exec` functionality found in -Docker and Kubernetes, so you get a new shell session within your existing -containers. To use this integration, you should deploy to Kubernetes using -the deployment variables above, ensuring any pods you create are labelled with -`app=$CI_ENVIRONMENT_SLUG`. GitLab will do the rest! - -[ee]: https://about.gitlab.com/products/ +This document was moved to [another location](../clusters/index.md). diff --git a/doc/user/project/integrations/project_services.md b/doc/user/project/integrations/project_services.md index 9496d6f2ce0..f19fc8ddf20 100644 --- a/doc/user/project/integrations/project_services.md +++ b/doc/user/project/integrations/project_services.md @@ -39,7 +39,6 @@ Click on the service links to see further configuration instructions and details | [Irker (IRC gateway)](irker.md) | Send IRC messages, on update, to a list of recipients through an Irker gateway | | [JIRA](jira.md) | JIRA issue tracker | | JetBrains TeamCity CI | A continuous integration and build server | -| [Kubernetes](kubernetes.md) _(Has been deprecated in GitLab 10.3)_ | A containerized deployment service | | [Mattermost slash commands](mattermost_slash_commands.md) | Mattermost chat and ChatOps slash commands | | [Mattermost Notifications](mattermost.md) | Receive event notifications in Mattermost | | [Microsoft teams](microsoft_teams.md) | Receive notifications for actions that happen on GitLab into a room on Microsoft Teams using Office 365 Connectors | -- cgit v1.2.1 From 761d890a68c92c49136937dbceda9f40bd714801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Javier=20L=C3=B3pez?= Date: Thu, 3 May 2018 11:02:26 +0200 Subject: Blacklisting attributes in the project import process --- .../security-fj-import-export-assignment.yml | 5 ++++ lib/gitlab/import_export/attribute_cleaner.rb | 11 ++++++-- lib/gitlab/import_export/attributes_finder.rb | 4 +++ lib/gitlab/import_export/import_export.yml | 2 -- lib/gitlab/import_export/project_tree_restorer.rb | 23 +++++++++++------ lib/gitlab/import_export/reader.rb | 2 +- lib/gitlab/import_export/relation_factory.rb | 10 +++++++- .../gitlab/import_export/attribute_cleaner_spec.rb | 29 +++++++++++++++++++--- spec/lib/gitlab/import_export/project.json | 2 ++ spec/lib/gitlab/import_export/project.light.json | 2 ++ .../import_export/project_tree_restorer_spec.rb | 9 +++++++ .../gitlab/import_export/relation_factory_spec.rb | 12 ++++++++- 12 files changed, 93 insertions(+), 18 deletions(-) create mode 100644 changelogs/unreleased/security-fj-import-export-assignment.yml diff --git a/changelogs/unreleased/security-fj-import-export-assignment.yml b/changelogs/unreleased/security-fj-import-export-assignment.yml new file mode 100644 index 00000000000..4bfd71d431a --- /dev/null +++ b/changelogs/unreleased/security-fj-import-export-assignment.yml @@ -0,0 +1,5 @@ +--- +title: Fixed bug that allowed importing arbitrary project attributes +merge_request: +author: +type: security diff --git a/lib/gitlab/import_export/attribute_cleaner.rb b/lib/gitlab/import_export/attribute_cleaner.rb index 34169319b26..7c9fc5c15bb 100644 --- a/lib/gitlab/import_export/attribute_cleaner.rb +++ b/lib/gitlab/import_export/attribute_cleaner.rb @@ -7,14 +7,15 @@ module Gitlab new(*args).clean end - def initialize(relation_hash:, relation_class:) + def initialize(relation_hash:, relation_class:, excluded_keys: []) @relation_hash = relation_hash @relation_class = relation_class + @excluded_keys = excluded_keys end def clean @relation_hash.reject do |key, _value| - prohibited_key?(key) || !@relation_class.attribute_method?(key) + prohibited_key?(key) || !@relation_class.attribute_method?(key) || excluded_key?(key) end.except('id') end @@ -23,6 +24,12 @@ module Gitlab def prohibited_key?(key) key.end_with?('_id') && !ALLOWED_REFERENCES.include?(key) end + + def excluded_key?(key) + return false if @excluded_keys.empty? + + @excluded_keys.include?(key) + end end end end diff --git a/lib/gitlab/import_export/attributes_finder.rb b/lib/gitlab/import_export/attributes_finder.rb index 56042ddecbf..0c8fda07294 100644 --- a/lib/gitlab/import_export/attributes_finder.rb +++ b/lib/gitlab/import_export/attributes_finder.rb @@ -32,6 +32,10 @@ module Gitlab @methods[key].nil? ? {} : { methods: @methods[key] } end + def find_excluded_keys(klass_name) + @excluded_attributes[klass_name.to_sym]&.map(&:to_s) || [] + end + private def find_attributes_only(value) diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml index 21ac7f7e0b6..36c7534cd7a 100644 --- a/lib/gitlab/import_export/import_export.yml +++ b/lib/gitlab/import_export/import_export.yml @@ -98,8 +98,6 @@ excluded_attributes: - :import_jid - :created_at - :updated_at - - :import_jid - - :import_jid - :id - :star_count - :last_activity_at diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index d5590dde40f..4eb67fbe11e 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -88,16 +88,18 @@ module Gitlab end def project_params - @project_params ||= json_params.merge(override_params) + @project_params ||= begin + attrs = json_params.merge(override_params) + + # Cleaning all imported and overridden params + Gitlab::ImportExport::AttributeCleaner.clean(relation_hash: attrs, + relation_class: Project, + excluded_keys: excluded_keys_for_relation(:project)) + end end def override_params - return {} unless params = @project.import_data&.data&.fetch('override_params', nil) - - @override_params ||= params.select do |key, _value| - Project.column_names.include?(key.to_s) && - !reader.project_tree[:except].include?(key.to_sym) - end + @override_params ||= @project.import_data&.data&.fetch('override_params', nil) || {} end def json_params @@ -171,7 +173,8 @@ module Gitlab relation_hash: parsed_relation_hash(relation_hash, relation.to_sym), members_mapper: members_mapper, user: @user, - project: @restored_project) + project: @restored_project, + excluded_keys: excluded_keys_for_relation(relation)) end.compact relation_hash_list.is_a?(Array) ? relation_array : relation_array.first @@ -192,6 +195,10 @@ module Gitlab def reader @reader ||= Gitlab::ImportExport::Reader.new(shared: @shared) end + + def excluded_keys_for_relation(relation) + @reader.attributes_finder.find_excluded_keys(relation) + end end end end diff --git a/lib/gitlab/import_export/reader.rb b/lib/gitlab/import_export/reader.rb index eb7f5120592..e621c40fc7a 100644 --- a/lib/gitlab/import_export/reader.rb +++ b/lib/gitlab/import_export/reader.rb @@ -1,7 +1,7 @@ module Gitlab module ImportExport class Reader - attr_reader :tree + attr_reader :tree, :attributes_finder def initialize(shared:) @shared = shared diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index e3e9f156fb4..301719406e4 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -36,13 +36,21 @@ module Gitlab new(*args).create end - def initialize(relation_sym:, relation_hash:, members_mapper:, user:, project:) + def initialize(relation_sym:, relation_hash:, members_mapper:, user:, project:, excluded_keys: []) @relation_name = OVERRIDES[relation_sym] || relation_sym @relation_hash = relation_hash.except('noteable_id') @members_mapper = members_mapper @user = user @project = project @imported_object_retries = 0 + + # Remove excluded keys from relation_hash + # We don't do this in the parsed_relation_hash because of the 'transformed attributes' + # For example, MergeRequestDiffFiles exports its diff attribute as utf8_diff. Then, + # in the create method that attribute is renamed to diff. And because diff is an excluded key, + # if we clean the excluded keys in the parsed_relation_hash, it will be removed + # from the object attributes and the export will fail. + @relation_hash.except!(*excluded_keys) end # Creates an object from an actual model with name "relation_sym" with params from diff --git a/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb b/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb index cd5a1b2982b..536cc359d39 100644 --- a/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb @@ -15,7 +15,10 @@ describe Gitlab::ImportExport::AttributeCleaner do 'project_id' => 99, 'user_id' => 99, 'random_id_in_the_middle' => 99, - 'notid' => 99 + 'notid' => 99, + 'import_source' => 'whatever', + 'import_type' => 'whatever', + 'non_existent_attr' => 'whatever' } end @@ -28,10 +31,30 @@ describe Gitlab::ImportExport::AttributeCleaner do } end + let(:excluded_keys) { %w[import_source import_type] } + + subject { described_class.clean(relation_hash: unsafe_hash, relation_class: relation_class, excluded_keys: excluded_keys) } + + before do + allow(relation_class).to receive(:attribute_method?).and_return(true) + allow(relation_class).to receive(:attribute_method?).with('non_existent_attr').and_return(false) + end + it 'removes unwanted attributes from the hash' do - # allow(relation_class).to receive(:attribute_method?).and_return(true) + expect(subject).to eq(post_safe_hash) + end + + it 'removes attributes not present in relation_class' do + expect(subject.keys).not_to include 'non_existent_attr' + end + + it 'removes excluded keys from the hash' do + expect(subject.keys).not_to include excluded_keys + end + + it 'does not remove excluded key if not listed' do parsed_hash = described_class.clean(relation_hash: unsafe_hash, relation_class: relation_class) - expect(parsed_hash).to eq(post_safe_hash) + expect(parsed_hash.keys).to eq post_safe_hash.keys + excluded_keys end end diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json index 6d63749296e..4d0cc1f196e 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -1,5 +1,7 @@ { "description": "Nisi et repellendus ut enim quo accusamus vel magnam.", + "import_type": "gitlab_project", + "creator_id": 123, "visibility_level": 10, "archived": false, "labels": [ diff --git a/spec/lib/gitlab/import_export/project.light.json b/spec/lib/gitlab/import_export/project.light.json index 5dbf0ed289b..c13cf4a0507 100644 --- a/spec/lib/gitlab/import_export/project.light.json +++ b/spec/lib/gitlab/import_export/project.light.json @@ -1,5 +1,7 @@ { "description": "Nisi et repellendus ut enim quo accusamus vel magnam.", + "import_type": "gitlab_project", + "creator_id": 123, "visibility_level": 10, "archived": false, "milestones": [ diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index 13a8c9adcee..68ddc947e02 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -23,6 +23,10 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do allow_any_instance_of(Gitlab::Git::Repository).to receive(:create_branch) project_tree_restorer = described_class.new(user: @user, shared: @shared, project: @project) + + expect(Gitlab::ImportExport::RelationFactory).to receive(:create).with(hash_including(excluded_keys: ['whatever'])).and_call_original.at_least(:once) + allow(project_tree_restorer).to receive(:excluded_keys_for_relation).and_return(['whatever']) + @restored_project_json = project_tree_restorer.restore end end @@ -248,6 +252,11 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do expect(labels.where(type: "ProjectLabel").count).to eq(results.fetch(:first_issue_labels, 0)) expect(labels.where(type: "ProjectLabel").where.not(group_id: nil).count).to eq(0) end + + it 'does not set params that are excluded from import_export settings' do + expect(project.import_type).to be_nil + expect(project.creator_id).not_to eq 123 + end end shared_examples 'restores group correctly' do |**results| diff --git a/spec/lib/gitlab/import_export/relation_factory_spec.rb b/spec/lib/gitlab/import_export/relation_factory_spec.rb index 5c61a5a2044..5f0dfd64b15 100644 --- a/spec/lib/gitlab/import_export/relation_factory_spec.rb +++ b/spec/lib/gitlab/import_export/relation_factory_spec.rb @@ -4,12 +4,14 @@ describe Gitlab::ImportExport::RelationFactory do let(:project) { create(:project) } let(:members_mapper) { double('members_mapper').as_null_object } let(:user) { create(:admin) } + let(:excluded_keys) { [] } let(:created_object) do described_class.create(relation_sym: relation_sym, relation_hash: relation_hash, members_mapper: members_mapper, user: user, - project: project) + project: project, + excluded_keys: excluded_keys) end context 'hook object' do @@ -67,6 +69,14 @@ describe Gitlab::ImportExport::RelationFactory do expect(created_object.service_id).not_to eq(service_id) end end + + context 'excluded attributes' do + let(:excluded_keys) { %w[url] } + + it 'are removed from the imported object' do + expect(created_object.url).to be_nil + end + end end # Mocks an ActiveRecordish object with the dodgy columns -- cgit v1.2.1 From ab3c6e76c03a5264cdde8c285b2df40ee6b8a324 Mon Sep 17 00:00:00 2001 From: Ben Bodenmiller Date: Wed, 16 May 2018 21:44:54 +0000 Subject: use postgres_role --- doc/administration/high_availability/database.md | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/doc/administration/high_availability/database.md b/doc/administration/high_availability/database.md index ca6d8d2de67..b5124b1d540 100644 --- a/doc/administration/high_availability/database.md +++ b/doc/administration/high_availability/database.md @@ -33,16 +33,7 @@ If you use a cloud-managed service, or provide your own PostgreSQL: external_url 'https://gitlab.example.com' # Disable all components except PostgreSQL - postgresql['enable'] = true - bootstrap['enable'] = false - nginx['enable'] = false - unicorn['enable'] = false - sidekiq['enable'] = false - redis['enable'] = false - prometheus['enable'] = false - gitaly['enable'] = false - gitlab_workhorse['enable'] = false - mailroom['enable'] = false + roles ['postgres_role'] # PostgreSQL configuration gitlab_rails['db_password'] = 'DB password' -- cgit v1.2.1 From a33d591602b40d224b4fdb74300e3b0d96bda7df Mon Sep 17 00:00:00 2001 From: Zeger-Jan van de Weg Date: Thu, 17 May 2018 15:19:32 +0200 Subject: Don't pass the repository path to Gitlab Shell This isn't a requirement, and removes deprecated method calls --- lib/api/helpers/internal_helpers.rb | 6 ------ lib/api/internal.rb | 2 +- spec/requests/api/internal_spec.rb | 12 ++++++------ 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb index abe3d353984..83151be82ad 100644 --- a/lib/api/helpers/internal_helpers.rb +++ b/lib/api/helpers/internal_helpers.rb @@ -89,12 +89,6 @@ module API end end - # Return the repository full path so that gitlab-shell has it when - # handling ssh commands - def repository_path - repository.path_to_repo - end - # Return the Gitaly Address if it is enabled def gitaly_payload(action) return unless %w[git-receive-pack git-upload-pack git-upload-archive].include?(action) diff --git a/lib/api/internal.rb b/lib/api/internal.rb index 6b72caea8fd..798a8dbb929 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -59,7 +59,7 @@ module API status: true, gl_repository: gl_repository, gl_username: user&.username, - repository_path: repository_path, + repository_path: nil, gitaly: gitaly_payload(params[:action]) } end diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index db8c5f963d6..506901095f1 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' describe API::Internal do - let(:user) { create(:user) } + set(:user) { create(:user) } let(:key) { create(:key, user: user) } - let(:project) { create(:project, :repository, :wiki_repo) } + set(:project) { create(:project, :repository, :wiki_repo) } let(:secret_token) { Gitlab::Shell.secret_token } let(:gl_repository) { "project-#{project.id}" } let(:reference_counter) { double('ReferenceCounter') } @@ -277,7 +277,7 @@ describe API::Internal do expect(response).to have_gitlab_http_status(200) expect(json_response["status"]).to be_truthy - expect(json_response["repository_path"]).to eq(project.wiki.repository.path_to_repo) + expect(json_response["repository_path"]).to be_nil expect(json_response["gl_repository"]).to eq("wiki-#{project.id}") expect(user).not_to have_an_activity_record end @@ -289,7 +289,7 @@ describe API::Internal do expect(response).to have_gitlab_http_status(200) expect(json_response["status"]).to be_truthy - expect(json_response["repository_path"]).to eq(project.wiki.repository.path_to_repo) + expect(json_response["repository_path"]).to be_nil expect(json_response["gl_repository"]).to eq("wiki-#{project.id}") expect(user).to have_an_activity_record end @@ -301,7 +301,7 @@ describe API::Internal do expect(response).to have_gitlab_http_status(200) expect(json_response["status"]).to be_truthy - expect(json_response["repository_path"]).to eq(project.repository.path_to_repo) + expect(json_response["repository_path"]).to be_nil expect(json_response["gl_repository"]).to eq("project-#{project.id}") expect(json_response["gitaly"]).not_to be_nil expect(json_response["gitaly"]["repository"]).not_to be_nil @@ -320,7 +320,7 @@ describe API::Internal do expect(response).to have_gitlab_http_status(200) expect(json_response["status"]).to be_truthy - expect(json_response["repository_path"]).to eq(project.repository.path_to_repo) + expect(json_response["repository_path"]).to be_nil expect(json_response["gl_repository"]).to eq("project-#{project.id}") expect(json_response["gitaly"]).not_to be_nil expect(json_response["gitaly"]["repository"]).not_to be_nil -- cgit v1.2.1 From 4bfd54f3d2e303d751d49834879867f3c62156e9 Mon Sep 17 00:00:00 2001 From: Bart Libert Date: Thu, 5 Apr 2018 13:44:18 +0200 Subject: Import bitbucket issues that are reported by an anonymous user For these kind of issues, the "reporter" field is present but zero. In such a case, "fetch" will not return the default value, but it will return nil. Hence, importing fails, because the "username" field of nil is referenced Fixes issue #44381 --- .../unreleased/fix-bitbucket_import_anonymous.yml | 5 ++++ lib/bitbucket/representation/issue.rb | 2 +- lib/gitlab/import_formatter.rb | 1 + spec/lib/gitlab/bitbucket_import/importer_spec.rb | 30 ++++++++++++++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/fix-bitbucket_import_anonymous.yml diff --git a/changelogs/unreleased/fix-bitbucket_import_anonymous.yml b/changelogs/unreleased/fix-bitbucket_import_anonymous.yml new file mode 100644 index 00000000000..6e214b3c957 --- /dev/null +++ b/changelogs/unreleased/fix-bitbucket_import_anonymous.yml @@ -0,0 +1,5 @@ +--- +title: Import bitbucket issues that are reported by an anonymous user +merge_request: 18199 +author: bartl +type: fixed diff --git a/lib/bitbucket/representation/issue.rb b/lib/bitbucket/representation/issue.rb index 054064395c3..44bcbc250b3 100644 --- a/lib/bitbucket/representation/issue.rb +++ b/lib/bitbucket/representation/issue.rb @@ -12,7 +12,7 @@ module Bitbucket end def author - raw.fetch('reporter', {}).fetch('username', nil) + raw.dig('reporter', 'username') end def description diff --git a/lib/gitlab/import_formatter.rb b/lib/gitlab/import_formatter.rb index 3e54456e936..4e611e7f16c 100644 --- a/lib/gitlab/import_formatter.rb +++ b/lib/gitlab/import_formatter.rb @@ -9,6 +9,7 @@ module Gitlab end def author_line(author) + author ||= "Anonymous" "*Created by: #{author}*\n\n" end end diff --git a/spec/lib/gitlab/bitbucket_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importer_spec.rb index c63120b0b29..05c232d22cf 100644 --- a/spec/lib/gitlab/bitbucket_import/importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/importer_spec.rb @@ -19,6 +19,18 @@ describe Gitlab::BitbucketImport::Importer do ] end + let(:reporters) do + [ + nil, + { "username" => "reporter1" }, + nil, + { "username" => "reporter2" }, + { "username" => "reporter1" }, + nil, + { "username" => "reporter3" } + ] + end + let(:sample_issues_statuses) do issues = [] @@ -36,6 +48,10 @@ describe Gitlab::BitbucketImport::Importer do } end + reporters.map.with_index do |reporter, index| + issues[index]['reporter'] = reporter + end + issues end @@ -147,5 +163,19 @@ describe Gitlab::BitbucketImport::Importer do expect(importer.errors).to be_empty end end + + describe 'issue import' do + it 'maps reporters to anonymous if bitbucket reporter is nil' do + allow(importer).to receive(:import_wiki) + importer.execute + + expect(project.issues.size).to eq(7) + expect(project.issues.where("description LIKE ?", '%Anonymous%').size).to eq(3) + expect(project.issues.where("description LIKE ?", '%reporter1%').size).to eq(2) + expect(project.issues.where("description LIKE ?", '%reporter2%').size).to eq(1) + expect(project.issues.where("description LIKE ?", '%reporter3%').size).to eq(1) + expect(importer.errors).to be_empty + end + end end end -- cgit v1.2.1 From 7a139c1602016485b8a2038dfc6121e47039c669 Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Thu, 24 May 2018 09:46:30 +0200 Subject: Add username to terms message in git and API calls This will make it clearer to users which account is being used to make the API/git call. So they know which account needs to be used to accept the terms. Closes #46649 --- changelogs/unreleased/bvl-add-username-to-terms-message.yml | 5 +++++ lib/gitlab/auth/user_access_denied_reason.rb | 8 ++++---- spec/lib/gitlab/auth/user_access_denied_reason_spec.rb | 3 ++- spec/lib/gitlab/git_access_spec.rb | 2 +- spec/requests/api/helpers_spec.rb | 2 +- 5 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 changelogs/unreleased/bvl-add-username-to-terms-message.yml diff --git a/changelogs/unreleased/bvl-add-username-to-terms-message.yml b/changelogs/unreleased/bvl-add-username-to-terms-message.yml new file mode 100644 index 00000000000..b95d87e9265 --- /dev/null +++ b/changelogs/unreleased/bvl-add-username-to-terms-message.yml @@ -0,0 +1,5 @@ +--- +title: Add username to terms message in git and API calls +merge_request: 19126 +author: +type: changed diff --git a/lib/gitlab/auth/user_access_denied_reason.rb b/lib/gitlab/auth/user_access_denied_reason.rb index af310aa12fc..1893cb001b2 100644 --- a/lib/gitlab/auth/user_access_denied_reason.rb +++ b/lib/gitlab/auth/user_access_denied_reason.rb @@ -8,12 +8,12 @@ module Gitlab def rejection_message case rejection_type when :internal - 'This action cannot be performed by internal users' + "This action cannot be performed by internal users" when :terms_not_accepted - 'You must accept the Terms of Service in order to perform this action. '\ - 'Please access GitLab from a web browser to accept these terms.' + "You (#{@user.to_reference}) must accept the Terms of Service in order to perform this action. "\ + "Please access GitLab from a web browser to accept these terms." else - 'Your account has been blocked.' + "Your account has been blocked." end end diff --git a/spec/lib/gitlab/auth/user_access_denied_reason_spec.rb b/spec/lib/gitlab/auth/user_access_denied_reason_spec.rb index fa209bed74e..002ce776be9 100644 --- a/spec/lib/gitlab/auth/user_access_denied_reason_spec.rb +++ b/spec/lib/gitlab/auth/user_access_denied_reason_spec.rb @@ -22,7 +22,8 @@ describe Gitlab::Auth::UserAccessDeniedReason do enforce_terms end - it { is_expected.to match /You must accept the Terms of Service/ } + it { is_expected.to match /must accept the Terms of Service/ } + it { is_expected.to include(user.username) } end context 'when the user is internal' do diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index 317a932d5a6..dfffea7797f 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -1055,7 +1055,7 @@ describe Gitlab::GitAccess do it 'blocks access when the user did not accept terms', :aggregate_failures do actions.each do |action| - expect { action.call }.to raise_unauthorized(/You must accept the Terms of Service in order to perform this action/) + expect { action.call }.to raise_unauthorized(/must accept the Terms of Service in order to perform this action/) end end diff --git a/spec/requests/api/helpers_spec.rb b/spec/requests/api/helpers_spec.rb index d3ab44c0d7e..d8a51f36dba 100644 --- a/spec/requests/api/helpers_spec.rb +++ b/spec/requests/api/helpers_spec.rb @@ -171,7 +171,7 @@ describe API::Helpers do end it 'returns a 403 when a user has not accepted the terms' do - expect { current_user }.to raise_error /You must accept the Terms of Service/ + expect { current_user }.to raise_error /must accept the Terms of Service/ end it 'sets the current user when the user accepted the terms' do -- cgit v1.2.1 From 34862867020da25828df9644721342318222ed79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 22 May 2018 14:28:43 +0200 Subject: Reduce CE/EE diff in spec/controllers/boards/issues_controller_spec.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/controllers/boards/issues_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/controllers/boards/issues_controller_spec.rb b/spec/controllers/boards/issues_controller_spec.rb index 4770e187db6..dcb0faffbd4 100644 --- a/spec/controllers/boards/issues_controller_spec.rb +++ b/spec/controllers/boards/issues_controller_spec.rb @@ -17,7 +17,7 @@ describe Boards::IssuesController do project.add_guest(guest) end - describe 'GET index' do + describe 'GET index', :request_store do let(:johndoe) { create(:user, avatar: fixture_file_upload(File.join(Rails.root, 'spec/fixtures/dk.png'))) } context 'with invalid board id' do -- cgit v1.2.1 From 2023ac4c28c7355e58e97c0192e8dceffb32efb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 22 May 2018 14:29:46 +0200 Subject: Reduce CE/EE diff in spec/controllers/projects/boards_controller_spec.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- .../controllers/projects/boards_controller_spec.rb | 66 ++++++++++++++++------ 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/spec/controllers/projects/boards_controller_spec.rb b/spec/controllers/projects/boards_controller_spec.rb index 4d765229bde..509f19ed030 100644 --- a/spec/controllers/projects/boards_controller_spec.rb +++ b/spec/controllers/projects/boards_controller_spec.rb @@ -27,6 +27,20 @@ describe Projects::BoardsController do expect(response).to render_template :index expect(response.content_type).to eq 'text/html' end + + context 'with unauthorized user' do + before do + allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true) + allow(Ability).to receive(:allowed?).with(user, :read_board, project).and_return(false) + end + + it 'returns a not found 404 response' do + list_boards + + expect(response).to have_gitlab_http_status(404) + expect(response.content_type).to eq 'text/html' + end + end end context 'when format is JSON' do @@ -40,18 +54,19 @@ describe Projects::BoardsController do expect(response).to match_response_schema('boards') expect(parsed_response.length).to eq 2 end - end - context 'with unauthorized user' do - before do - allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true) - allow(Ability).to receive(:allowed?).with(user, :read_board, project).and_return(false) - end + context 'with unauthorized user' do + before do + allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true) + allow(Ability).to receive(:allowed?).with(user, :read_board, project).and_return(false) + end - it 'returns a not found 404 response' do - list_boards + it 'returns a not found 404 response' do + list_boards format: :json - expect(response).to have_gitlab_http_status(404) + expect(response).to have_gitlab_http_status(404) + expect(response.content_type).to eq 'application/json' + end end end @@ -88,6 +103,20 @@ describe Projects::BoardsController do expect(response).to render_template :show expect(response.content_type).to eq 'text/html' end + + context 'with unauthorized user' do + before do + allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true) + allow(Ability).to receive(:allowed?).with(user, :read_board, project).and_return(false) + end + + it 'returns a not found 404 response' do + read_board board: board + + expect(response).to have_gitlab_http_status(404) + expect(response.content_type).to eq 'text/html' + end + end end context 'when format is JSON' do @@ -96,18 +125,19 @@ describe Projects::BoardsController do expect(response).to match_response_schema('board') end - end - context 'with unauthorized user' do - before do - allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true) - allow(Ability).to receive(:allowed?).with(user, :read_board, project).and_return(false) - end + context 'with unauthorized user' do + before do + allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true) + allow(Ability).to receive(:allowed?).with(user, :read_board, project).and_return(false) + end - it 'returns a not found 404 response' do - read_board board: board + it 'returns a not found 404 response' do + read_board board: board, format: :json - expect(response).to have_gitlab_http_status(404) + expect(response).to have_gitlab_http_status(404) + expect(response.content_type).to eq 'application/json' + end end end -- cgit v1.2.1 From 248cefc7091224d62d4559b9a49813a27b793a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 22 May 2018 14:38:31 +0200 Subject: Reduce CE/EE diff in spec/controllers/projects/branches_controller_spec.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/controllers/projects/branches_controller_spec.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index 16fb377b002..4860ea5dcce 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -146,6 +146,24 @@ describe Projects::BranchesController do it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes' end + + it 'redirects to autodeploy setup page' do + result = { status: :success, branch: double(name: branch) } + + create(:cluster, :provided_by_gcp, projects: [project]) + + expect_any_instance_of(CreateBranchService).to receive(:execute).and_return(result) + expect(SystemNoteService).to receive(:new_issue_branch).and_return(true) + + post :create, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + branch_name: branch, + issue_iid: issue.iid + + expect(response.location).to include(project_new_blob_path(project, branch)) + expect(response).to have_gitlab_http_status(302) + end end context 'when create branch service fails' do -- cgit v1.2.1 From 981b8ab7bd72c8500f8cc7f64c9eeff36f454851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 22 May 2018 14:40:47 +0200 Subject: Reduce CE/EE diff in app/controllers/projects/clusters_controller.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- app/controllers/projects/clusters_controller.rb | 13 ------------- spec/controllers/projects/clusters_controller_spec.rb | 9 ++++----- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/app/controllers/projects/clusters_controller.rb b/app/controllers/projects/clusters_controller.rb index aeaba3a0acf..d58039b7d42 100644 --- a/app/controllers/projects/clusters_controller.rb +++ b/app/controllers/projects/clusters_controller.rb @@ -71,19 +71,6 @@ class Projects::ClustersController < Projects::ApplicationController .present(current_user: current_user) end - def create_params - params.require(:cluster).permit( - :enabled, - :name, - :provider_type, - provider_gcp_attributes: [ - :gcp_project_id, - :zone, - :num_nodes, - :machine_type - ]) - end - def update_params if cluster.managed? params.require(:cluster).permit( diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb index 82b20e12850..380e50c8cac 100644 --- a/spec/controllers/projects/clusters_controller_spec.rb +++ b/spec/controllers/projects/clusters_controller_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' describe Projects::ClustersController do include AccessMatchersForController - include GoogleApi::CloudPlatformHelpers set(:project) { create(:project) } @@ -333,7 +332,7 @@ describe Projects::ClustersController do context 'when cluster is provided by GCP' do context 'when cluster is created' do - let!(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) } + let!(:cluster) { create(:cluster, :provided_by_gcp, :production_environment, projects: [project]) } it "destroys and redirects back to clusters list" do expect { go } @@ -347,7 +346,7 @@ describe Projects::ClustersController do end context 'when cluster is being created' do - let!(:cluster) { create(:cluster, :providing_by_gcp, projects: [project]) } + let!(:cluster) { create(:cluster, :providing_by_gcp, :production_environment, projects: [project]) } it "destroys and redirects back to clusters list" do expect { go } @@ -361,7 +360,7 @@ describe Projects::ClustersController do end context 'when cluster is provided by user' do - let!(:cluster) { create(:cluster, :provided_by_user, projects: [project]) } + let!(:cluster) { create(:cluster, :provided_by_user, :production_environment, projects: [project]) } it "destroys and redirects back to clusters list" do expect { go } @@ -376,7 +375,7 @@ describe Projects::ClustersController do end describe 'security' do - set(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) } + set(:cluster) { create(:cluster, :provided_by_gcp, :production_environment, projects: [project]) } it { expect { go }.to be_allowed_for(:admin) } it { expect { go }.to be_allowed_for(:owner).of(project) } -- cgit v1.2.1 From 660439e968c77f216b0579250d0042d62ea4cb95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 22 May 2018 15:12:47 +0200 Subject: Reduce CE/EE diff in spec/controllers/projects/environments_controller_spec.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- app/controllers/projects/environments_controller.rb | 10 ++++++++++ spec/controllers/projects/environments_controller_spec.rb | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index 52d528e816e..0821362f5df 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -7,6 +7,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController before_action :authorize_admin_environment!, only: [:terminal, :terminal_websocket_authorize] before_action :environment, only: [:show, :edit, :update, :stop, :terminal, :terminal_websocket_authorize, :metrics] before_action :verify_api_request!, only: :terminal_websocket_authorize + before_action :expire_etag_cache, only: [:index] def index @environments = project.environments @@ -148,6 +149,15 @@ class Projects::EnvironmentsController < Projects::ApplicationController Gitlab::Workhorse.verify_api_request!(request.headers) end + def expire_etag_cache + return if request.format.json? + + # this forces to reload json content + Gitlab::EtagCaching::Store.new.tap do |store| + store.touch(project_environments_path(project, format: :json)) + end + end + def environment_params params.require(:environment).permit(:name, :external_url) end diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb index ff9ab53d8c3..47d4942acbd 100644 --- a/spec/controllers/projects/environments_controller_spec.rb +++ b/spec/controllers/projects/environments_controller_spec.rb @@ -21,6 +21,13 @@ describe Projects::EnvironmentsController do expect(response).to have_gitlab_http_status(:ok) end + + it 'expires etag cache to force reload environments list' do + expect_any_instance_of(Gitlab::EtagCaching::Store) + .to receive(:touch).with(project_environments_path(project, format: :json)) + + get :index, environment_params + end end context 'when requesting JSON response for folders' do -- cgit v1.2.1 From 53e30e15281f4633a06b73d23ca1a093bb12597c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 22 May 2018 15:15:31 +0200 Subject: Reduce CE/EE diff in spec/controllers/projects/group_links_controller_spec.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/controllers/projects/group_links_controller_spec.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/spec/controllers/projects/group_links_controller_spec.rb b/spec/controllers/projects/group_links_controller_spec.rb index 5bfc3d31401..72f6af112b3 100644 --- a/spec/controllers/projects/group_links_controller_spec.rb +++ b/spec/controllers/projects/group_links_controller_spec.rb @@ -21,6 +21,18 @@ describe Projects::GroupLinksController do end end + context 'when project is not allowed to be shared with a group' do + before do + group.update_attributes(share_with_group_lock: false) + end + + include_context 'link project to group' + + it 'responds with status 404' do + expect(response).to have_gitlab_http_status(404) + end + end + context 'when user has access to group he want to link project to' do before do group.add_developer(user) -- cgit v1.2.1 From ee9e4d465219010ec8d5f954dcee9496e30a0d76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 22 May 2018 15:23:56 +0200 Subject: Reduce CE/EE diff in spec/controllers/projects/imports_controller_spec.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/controllers/projects/imports_controller_spec.rb | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/spec/controllers/projects/imports_controller_spec.rb b/spec/controllers/projects/imports_controller_spec.rb index 7fb4c1b7425..011843baffc 100644 --- a/spec/controllers/projects/imports_controller_spec.rb +++ b/spec/controllers/projects/imports_controller_spec.rb @@ -2,16 +2,15 @@ require 'spec_helper' describe Projects::ImportsController do let(:user) { create(:user) } + let(:project) { create(:project) } + + before do + sign_in(user) + project.add_master(user) + end describe 'GET #show' do context 'when repository does not exists' do - let(:project) { create(:project) } - - before do - sign_in(user) - project.add_master(user) - end - it 'renders template' do get :show, namespace_id: project.namespace.to_param, project_id: project @@ -28,11 +27,6 @@ describe Projects::ImportsController do context 'when repository exists' do let(:project) { create(:project_empty_repo, import_url: 'https://github.com/vim/vim.git') } - before do - sign_in(user) - project.add_master(user) - end - context 'when import is in progress' do before do project.update_attribute(:import_status, :started) -- cgit v1.2.1 From ab36cf05c8fa7ba0861487d0580444dec4e896e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 22 May 2018 17:22:51 +0200 Subject: Reduce CE/EE diff in spec/controllers/projects/issues_controller_spec.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/controllers/projects/issues_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index ca86b0bc737..106611b37c9 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -1,4 +1,4 @@ -require('spec_helper') +require 'spec_helper' describe Projects::IssuesController do let(:project) { create(:project) } -- cgit v1.2.1 From 7736b518121f853b44732b851034e8cfca910e15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 22 May 2018 17:25:43 +0200 Subject: Reduce CE/EE diff in spec/controllers/projects/project_members_controller_spec.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/controllers/projects/project_members_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb index 46b08a03b19..d84b31ad978 100644 --- a/spec/controllers/projects/project_members_controller_spec.rb +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -184,7 +184,7 @@ describe Projects::ProjectMembersController do project.add_master(user) end - it 'cannot remove himself from the project' do + it 'cannot remove themselves from the project' do delete :leave, namespace_id: project.namespace, project_id: project -- cgit v1.2.1 From 9471c3f673abab7b3179c1dc2931a2c44aa1f3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 24 May 2018 12:02:41 +0200 Subject: Try to fetch the CE branch in EE because sometimes it has the same name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- lib/gitlab/ee_compat_check.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb index 8cf59fa8e28..8c72d00c1f3 100644 --- a/lib/gitlab/ee_compat_check.rb +++ b/lib/gitlab/ee_compat_check.rb @@ -138,8 +138,8 @@ module Gitlab def ee_branch_presence_check! ee_remotes.keys.each do |remote| - [ee_branch_prefix, ee_branch_suffix].each do |branch| - _, status = step("Fetching #{remote}/#{ee_branch_prefix}", %W[git fetch #{remote} #{branch}]) + [ce_branch, ee_branch_prefix, ee_branch_suffix].each do |branch| + _, status = step("Fetching #{remote}/#{branch}", %W[git fetch #{remote} #{branch}]) if status.zero? @ee_remote_with_branch = remote -- cgit v1.2.1 From bb8f2520b4254c9dabe377df48e29c5f17894a1d Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Wed, 16 May 2018 12:46:18 -0300 Subject: Persist truncated note diffs on a new table We request Gitaly in a N+1 manner to build discussion diffs. Once the diffs are from different revisions, it's hard to make a single request to the service in order to build the whole response. With this change we solve this problem and simplify a lot fetching this piece of info. --- app/models/concerns/diff_file.rb | 9 +++ app/models/diff_note.rb | 67 ++++++++++++++---- app/models/merge_request_diff_file.rb | 7 +- app/models/note.rb | 4 +- app/models/note_diff_file.rb | 7 ++ app/workers/all_queues.yml | 1 + app/workers/create_note_diff_file_worker.rb | 9 +++ .../unreleased/45190-create-notes-diff-files.yml | 5 ++ config/sidekiq_queues.yml | 1 + .../20180515121227_create_notes_diff_files.rb | 21 ++++++ db/schema.rb | 15 ++++ lib/gitlab/diff/file.rb | 7 ++ spec/lib/gitlab/diff/file_spec.rb | 54 ++++++++++++++ spec/lib/gitlab/import_export/all_models.yml | 1 + spec/models/concerns/discussion_on_diff_spec.rb | 2 +- spec/models/diff_note_spec.rb | 62 +++++++++++++++- spec/models/note_diff_file_spec.rb | 11 +++ spec/services/notes/create_service_spec.rb | 82 ++++++++++++++++++++++ spec/workers/create_note_diff_file_worker_spec.rb | 16 +++++ 19 files changed, 357 insertions(+), 24 deletions(-) create mode 100644 app/models/concerns/diff_file.rb create mode 100644 app/models/note_diff_file.rb create mode 100644 app/workers/create_note_diff_file_worker.rb create mode 100644 changelogs/unreleased/45190-create-notes-diff-files.yml create mode 100644 db/migrate/20180515121227_create_notes_diff_files.rb create mode 100644 spec/models/note_diff_file_spec.rb create mode 100644 spec/workers/create_note_diff_file_worker_spec.rb diff --git a/app/models/concerns/diff_file.rb b/app/models/concerns/diff_file.rb new file mode 100644 index 00000000000..72332072012 --- /dev/null +++ b/app/models/concerns/diff_file.rb @@ -0,0 +1,9 @@ +module DiffFile + extend ActiveSupport::Concern + + def to_hash + keys = Gitlab::Git::Diff::SERIALIZE_KEYS - [:diff] + + as_json(only: keys).merge(diff: diff).with_indifferent_access + end +end diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb index 616a626419b..d752d5bcdee 100644 --- a/app/models/diff_note.rb +++ b/app/models/diff_note.rb @@ -3,6 +3,7 @@ # A note of this type can be resolvable. class DiffNote < Note include NoteOnDiff + include Gitlab::Utils::StrongMemoize NOTEABLE_TYPES = %w(MergeRequest Commit).freeze @@ -12,7 +13,6 @@ class DiffNote < Note validates :original_position, presence: true validates :position, presence: true - validates :diff_line, presence: true, if: :on_text? validates :line_code, presence: true, line_code: true, if: :on_text? validates :noteable_type, inclusion: { in: NOTEABLE_TYPES } validate :positions_complete @@ -23,6 +23,7 @@ class DiffNote < Note before_validation :update_position, on: :create, if: :on_text? before_validation :set_line_code, if: :on_text? after_save :keep_around_commits + after_commit :create_diff_file, on: :create def discussion_class(*) DiffDiscussion @@ -53,21 +54,25 @@ class DiffNote < Note position.position_type == "image" end + def create_diff_file + return unless should_create_diff_file? + + diff_file = fetch_diff_file + diff_line = diff_file.line_for_position(self.original_position) + + creation_params = diff_file.diff.to_hash + .except(:too_large) + .merge(diff: diff_file.diff_hunk(diff_line)) + + create_note_diff_file(creation_params) + end + def diff_file - @diff_file ||= - begin - if created_at_diff?(noteable.diff_refs) - # We're able to use the already persisted diffs (Postgres) if we're - # presenting a "current version" of the MR discussion diff. - # So no need to make an extra Gitaly diff request for it. - # As an extra benefit, the returned `diff_file` already - # has `highlighted_diff_lines` data set from Redis on - # `Diff::FileCollection::MergeRequestDiff`. - noteable.diffs(paths: original_position.paths, expanded: true).diff_files.first - else - original_position.diff_file(self.project.repository) - end - end + strong_memoize(:diff_file) do + enqueue_diff_file_creation_job if should_create_diff_file? + + fetch_diff_file + end end def diff_line @@ -98,6 +103,38 @@ class DiffNote < Note private + def enqueue_diff_file_creation_job + # Avoid enqueuing multiple file creation jobs at once for a note (i.e. + # parallel calls to `DiffNote#diff_file`). + lease = Gitlab::ExclusiveLease.new("note_diff_file_creation:#{id}", timeout: 1.hour.to_i) + return unless lease.try_obtain + + CreateNoteDiffFileWorker.perform_async(id) + end + + def should_create_diff_file? + on_text? && note_diff_file.nil? && self == discussion.first_note + end + + def fetch_diff_file + if note_diff_file + diff = Gitlab::Git::Diff.new(note_diff_file.to_hash) + Gitlab::Diff::File.new(diff, + repository: project.repository, + diff_refs: original_position.diff_refs) + elsif created_at_diff?(noteable.diff_refs) + # We're able to use the already persisted diffs (Postgres) if we're + # presenting a "current version" of the MR discussion diff. + # So no need to make an extra Gitaly diff request for it. + # As an extra benefit, the returned `diff_file` already + # has `highlighted_diff_lines` data set from Redis on + # `Diff::FileCollection::MergeRequestDiff`. + noteable.diffs(paths: original_position.paths, expanded: true).diff_files.first + else + original_position.diff_file(self.project.repository) + end + end + def supported? for_commit? || self.noteable.has_complete_diff_refs? end diff --git a/app/models/merge_request_diff_file.rb b/app/models/merge_request_diff_file.rb index 1199ff5af22..cd8ba6b904d 100644 --- a/app/models/merge_request_diff_file.rb +++ b/app/models/merge_request_diff_file.rb @@ -1,5 +1,6 @@ class MergeRequestDiffFile < ActiveRecord::Base include Gitlab::EncodingHelper + include DiffFile belongs_to :merge_request_diff @@ -12,10 +13,4 @@ class MergeRequestDiffFile < ActiveRecord::Base def diff binary? ? super.unpack('m0').first : super end - - def to_hash - keys = Gitlab::Git::Diff::SERIALIZE_KEYS - [:diff] - - as_json(only: keys).merge(diff: diff).with_indifferent_access - end end diff --git a/app/models/note.rb b/app/models/note.rb index 109405d3f17..02f7a9b1e4f 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -63,6 +63,7 @@ class Note < ActiveRecord::Base has_many :todos has_many :events, as: :target, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_one :system_note_metadata + has_one :note_diff_file, inverse_of: :diff_note, foreign_key: :diff_note_id delegate :gfm_reference, :local_reference, to: :noteable delegate :name, to: :project, prefix: true @@ -100,7 +101,8 @@ class Note < ActiveRecord::Base scope :inc_author_project, -> { includes(:project, :author) } scope :inc_author, -> { includes(:author) } scope :inc_relations_for_view, -> do - includes(:project, :author, :updated_by, :resolved_by, :award_emoji, :system_note_metadata) + includes(:project, :author, :updated_by, :resolved_by, :award_emoji, + :system_note_metadata, :note_diff_file) end scope :diff_notes, -> { where(type: %w(LegacyDiffNote DiffNote)) } diff --git a/app/models/note_diff_file.rb b/app/models/note_diff_file.rb new file mode 100644 index 00000000000..e688018a6d9 --- /dev/null +++ b/app/models/note_diff_file.rb @@ -0,0 +1,7 @@ +class NoteDiffFile < ActiveRecord::Base + include DiffFile + + belongs_to :diff_note, inverse_of: :note_diff_file + + validates :diff_note, presence: true +end diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index b6433eb3eff..d07865a4043 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -115,3 +115,4 @@ - upload_checksum - web_hook - repository_update_remote_mirror +- create_note_diff_file diff --git a/app/workers/create_note_diff_file_worker.rb b/app/workers/create_note_diff_file_worker.rb new file mode 100644 index 00000000000..624b638a24e --- /dev/null +++ b/app/workers/create_note_diff_file_worker.rb @@ -0,0 +1,9 @@ +class CreateNoteDiffFileWorker + include ApplicationWorker + + def perform(diff_note_id) + diff_note = DiffNote.find(diff_note_id) + + diff_note.create_diff_file + end +end diff --git a/changelogs/unreleased/45190-create-notes-diff-files.yml b/changelogs/unreleased/45190-create-notes-diff-files.yml new file mode 100644 index 00000000000..efe322b682d --- /dev/null +++ b/changelogs/unreleased/45190-create-notes-diff-files.yml @@ -0,0 +1,5 @@ +--- +title: Persist truncated note diffs on a new table +merge_request: +author: +type: performance diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml index e1e8f36b663..d16060e8f45 100644 --- a/config/sidekiq_queues.yml +++ b/config/sidekiq_queues.yml @@ -75,4 +75,5 @@ - [pipeline_background, 1] - [repository_update_remote_mirror, 1] - [repository_remove_remote, 1] + - [create_note_diff_file, 1] diff --git a/db/migrate/20180515121227_create_notes_diff_files.rb b/db/migrate/20180515121227_create_notes_diff_files.rb new file mode 100644 index 00000000000..7108bc1a64b --- /dev/null +++ b/db/migrate/20180515121227_create_notes_diff_files.rb @@ -0,0 +1,21 @@ +class CreateNotesDiffFiles < ActiveRecord::Migration + DOWNTIME = false + + disable_ddl_transaction! + + def change + create_table :note_diff_files do |t| + t.references :diff_note, references: :notes, null: false, index: { unique: true } + t.text :diff, null: false + t.boolean :new_file, null: false + t.boolean :renamed_file, null: false + t.boolean :deleted_file, null: false + t.string :a_mode, null: false + t.string :b_mode, null: false + t.text :new_path, null: false + t.text :old_path, null: false + end + + add_foreign_key :note_diff_files, :notes, column: :diff_note_id, on_delete: :cascade + end +end diff --git a/db/schema.rb b/db/schema.rb index 37d336b9928..884e333874c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1302,6 +1302,20 @@ ActiveRecord::Schema.define(version: 20180521171529) do add_index "namespaces", ["runners_token"], name: "index_namespaces_on_runners_token", unique: true, using: :btree add_index "namespaces", ["type"], name: "index_namespaces_on_type", using: :btree + create_table "note_diff_files", force: :cascade do |t| + t.integer "diff_note_id", null: false + t.text "diff", null: false + t.boolean "new_file", null: false + t.boolean "renamed_file", null: false + t.boolean "deleted_file", null: false + t.string "a_mode", null: false + t.string "b_mode", null: false + t.text "new_path", null: false + t.text "old_path", null: false + end + + add_index "note_diff_files", ["diff_note_id"], name: "index_note_diff_files_on_diff_note_id", unique: true, using: :btree + create_table "notes", force: :cascade do |t| t.text "note" t.string "noteable_type" @@ -2243,6 +2257,7 @@ ActiveRecord::Schema.define(version: 20180521171529) do add_foreign_key "merge_requests_closing_issues", "merge_requests", on_delete: :cascade add_foreign_key "milestones", "namespaces", column: "group_id", name: "fk_95650a40d4", on_delete: :cascade add_foreign_key "milestones", "projects", name: "fk_9bd0a0c791", on_delete: :cascade + add_foreign_key "note_diff_files", "notes", column: "diff_note_id", on_delete: :cascade add_foreign_key "notes", "projects", name: "fk_99e097b079", on_delete: :cascade add_foreign_key "oauth_openid_requests", "oauth_access_grants", column: "access_grant_id", name: "fk_oauth_openid_requests_oauth_access_grants_access_grant_id" add_foreign_key "pages_domains", "projects", name: "fk_ea2f6dfc6f", on_delete: :cascade diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index 014854da55c..765fb0289a8 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -76,6 +76,13 @@ module Gitlab line_code(line) if line end + # Returns the raw diff content up to the given line index + def diff_hunk(diff_line) + # Adding 2 because of the @@ diff header and Enum#take should consider + # an extra line, because we're passing an index. + raw_diff.each_line.take(diff_line.index + 2).join + end + def old_sha diff_refs&.base_sha end diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb index 0c2e18c268a..0588fe935c3 100644 --- a/spec/lib/gitlab/diff/file_spec.rb +++ b/spec/lib/gitlab/diff/file_spec.rb @@ -468,4 +468,58 @@ describe Gitlab::Diff::File do end end end + + describe '#diff_hunk' do + let(:raw_diff) do + < path } +- options = { chdir: path } ++ ++ vars = { ++ "PWD" => path ++ } ++ ++ options = { ++ chdir: path ++ } + + unless File.directory?(path) + FileUtils.mkdir_p(path) +@@ -19,6 +25,7 @@ module Popen + + @cmd_output = "" + @cmd_status = 0 ++ + Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| + @cmd_output << stdout.read + @cmd_output << stderr.read +EOS + end + + it 'returns raw diff up to given line index' do + allow(diff_file).to receive(:raw_diff) { raw_diff } + diff_line = instance_double(Gitlab::Diff::Line, index: 5) + + diff_hunk = < Date: Thu, 26 Apr 2018 19:45:22 -0700 Subject: Fix project destruction failing due to idle in transaction timeouts When deleting associated records, Rails loads all associations into memory (https://github.com/rails/rails/issues/22510) before destroying them. This can cause a surge in memory and cause destruction of objects to fail due to idle in transaction database timeouts. This fix is inspired from https://github.com/thisismydesign to destroy `has_many` relationships in batches. Closes #44610 --- .../batch_destroy_dependent_associations.rb | 28 ++++++++++ app/models/project.rb | 1 + app/services/projects/destroy_service.rb | 8 ++- .../unreleased/sh-batch-dependent-destroys.yml | 5 ++ .../batch_destroy_dependent_associations_spec.rb | 60 ++++++++++++++++++++++ 5 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 app/models/concerns/batch_destroy_dependent_associations.rb create mode 100644 changelogs/unreleased/sh-batch-dependent-destroys.yml create mode 100644 spec/models/concerns/batch_destroy_dependent_associations_spec.rb diff --git a/app/models/concerns/batch_destroy_dependent_associations.rb b/app/models/concerns/batch_destroy_dependent_associations.rb new file mode 100644 index 00000000000..353ee2e73d0 --- /dev/null +++ b/app/models/concerns/batch_destroy_dependent_associations.rb @@ -0,0 +1,28 @@ +# Provides a way to work around Rails issue where dependent objects are all +# loaded into memory before destroyed: https://github.com/rails/rails/issues/22510. +# +# This concern allows an ActiveRecord module to destroy all its dependent +# associations in batches. The idea is borrowed from https://github.com/thisismydesign/batch_dependent_associations. +# +# The differences here with that gem: +# +# 1. We allow excluding certain associations. +# 2. We don't need to support delete_all since we can use the EachBatch concern. +module BatchDestroyDependentAssociations + extend ActiveSupport::Concern + + DEPENDENT_ASSOCIATIONS_BATCH_SIZE = 1000 + + def dependent_associations_to_destroy + self.class.reflect_on_all_associations(:has_many).select { |assoc| assoc.options[:dependent] == :destroy } + end + + def destroy_dependent_associations_in_batches(exclude: []) + dependent_associations_to_destroy.each do |association| + next if exclude.include?(association.name) + + # rubocop:disable GitlabSecurity/PublicSend + public_send(association.name).find_each(batch_size: DEPENDENT_ASSOCIATIONS_BATCH_SIZE, &:destroy) + end + end +end diff --git a/app/models/project.rb b/app/models/project.rb index 0fe9f8880b4..e275ac4dc6f 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -24,6 +24,7 @@ class Project < ActiveRecord::Base include ChronicDurationAttribute include FastDestroyAll::Helpers include WithUploads + include BatchDestroyDependentAssociations extend Gitlab::ConfigHelper diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb index adbc498d0bf..04a293a0fd6 100644 --- a/app/services/projects/destroy_service.rb +++ b/app/services/projects/destroy_service.rb @@ -124,7 +124,13 @@ module Projects trash_repositories! - project.team.truncate + # Rails attempts to load all related records into memory before + # destroying: https://github.com/rails/rails/issues/22510 + # This ensures we delete records in batches. + # + # Exclude container repositories because its before_destroy would be + # called multiple times, and it doesn't destroy any database records. + project.destroy_dependent_associations_in_batches(exclude: [:container_repositories]) project.destroy! end end diff --git a/changelogs/unreleased/sh-batch-dependent-destroys.yml b/changelogs/unreleased/sh-batch-dependent-destroys.yml new file mode 100644 index 00000000000..e297badc1fa --- /dev/null +++ b/changelogs/unreleased/sh-batch-dependent-destroys.yml @@ -0,0 +1,5 @@ +--- +title: Fix project destruction failing due to idle in transaction timeouts +merge_request: +author: +type: fixed diff --git a/spec/models/concerns/batch_destroy_dependent_associations_spec.rb b/spec/models/concerns/batch_destroy_dependent_associations_spec.rb new file mode 100644 index 00000000000..c16b245bea8 --- /dev/null +++ b/spec/models/concerns/batch_destroy_dependent_associations_spec.rb @@ -0,0 +1,60 @@ +require 'spec_helper' + +describe BatchDestroyDependentAssociations do + class TestProject < ActiveRecord::Base + self.table_name = 'projects' + + has_many :builds, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent + has_many :notification_settings, as: :source, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent + has_many :pages_domains + has_many :todos + + include BatchDestroyDependentAssociations + end + + describe '#dependent_associations_to_destroy' do + set(:project) { TestProject.new } + + it 'returns the right associations' do + expect(project.dependent_associations_to_destroy.map(&:name)).to match_array([:builds]) + end + end + + describe '#destroy_dependent_associations_in_batches' do + set(:project) { create(:project) } + set(:build) { create(:ci_build, project: project) } + set(:notification_setting) { create(:notification_setting, project: project) } + let!(:todos) { create(:todo, project: project) } + + it 'destroys multiple builds' do + create(:ci_build, project: project) + + expect(Ci::Build.count).to eq(2) + + project.destroy_dependent_associations_in_batches + + expect(Ci::Build.count).to eq(0) + end + + it 'destroys builds in batches' do + expect(project).to receive_message_chain(:builds, :find_each).and_yield(build) + expect(build).to receive(:destroy).and_call_original + + project.destroy_dependent_associations_in_batches + + expect(Ci::Build.count).to eq(0) + expect(Todo.count).to eq(1) + expect(User.count).to be > 0 + expect(NotificationSetting.count).to eq(User.count) + end + + it 'excludes associations' do + project.destroy_dependent_associations_in_batches(exclude: [:builds]) + + expect(Ci::Build.count).to eq(1) + expect(Todo.count).to eq(1) + expect(User.count).to be > 0 + expect(NotificationSetting.count).to eq(User.count) + end + end +end -- cgit v1.2.1 From 8fad07383ada021fc995294fd0fe0f77fe37da35 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 25 May 2018 13:45:29 +0200 Subject: Return '/' as a bogus repo path to gitlab-shell --- lib/api/internal.rb | 6 +++++- spec/requests/api/internal_spec.rb | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/api/internal.rb b/lib/api/internal.rb index 798a8dbb929..a41270fa85f 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -59,7 +59,11 @@ module API status: true, gl_repository: gl_repository, gl_username: user&.username, - repository_path: nil, + + # This repository_path is a bogus value but gitlab-shell still requires + # its presence. https://gitlab.com/gitlab-org/gitlab-shell/issues/135 + repository_path: '/', + gitaly: gitaly_payload(params[:action]) } end diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 506901095f1..5dc3ddd4b36 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -277,7 +277,7 @@ describe API::Internal do expect(response).to have_gitlab_http_status(200) expect(json_response["status"]).to be_truthy - expect(json_response["repository_path"]).to be_nil + expect(json_response["repository_path"]).to eq('/') expect(json_response["gl_repository"]).to eq("wiki-#{project.id}") expect(user).not_to have_an_activity_record end @@ -289,7 +289,7 @@ describe API::Internal do expect(response).to have_gitlab_http_status(200) expect(json_response["status"]).to be_truthy - expect(json_response["repository_path"]).to be_nil + expect(json_response["repository_path"]).to eq('/') expect(json_response["gl_repository"]).to eq("wiki-#{project.id}") expect(user).to have_an_activity_record end @@ -301,7 +301,7 @@ describe API::Internal do expect(response).to have_gitlab_http_status(200) expect(json_response["status"]).to be_truthy - expect(json_response["repository_path"]).to be_nil + expect(json_response["repository_path"]).to eq('/') expect(json_response["gl_repository"]).to eq("project-#{project.id}") expect(json_response["gitaly"]).not_to be_nil expect(json_response["gitaly"]["repository"]).not_to be_nil @@ -320,7 +320,7 @@ describe API::Internal do expect(response).to have_gitlab_http_status(200) expect(json_response["status"]).to be_truthy - expect(json_response["repository_path"]).to be_nil + expect(json_response["repository_path"]).to eq('/') expect(json_response["gl_repository"]).to eq("project-#{project.id}") expect(json_response["gitaly"]).not_to be_nil expect(json_response["gitaly"]["repository"]).not_to be_nil -- cgit v1.2.1 From 6fb35c843230465de3a554d4d752ee5eecb07166 Mon Sep 17 00:00:00 2001 From: Lukas Eipert Date: Fri, 25 May 2018 16:43:51 +0200 Subject: backport changes from https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/5852 --- app/assets/stylesheets/pages/pipelines.scss | 102 +++++++++++++++++----------- 1 file changed, 61 insertions(+), 41 deletions(-) diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 1264d977b2f..cd099b88952 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -1,3 +1,30 @@ +@mixin flat-connector-before($length: 44px) { + &::before { + content: ''; + position: absolute; + top: 48%; + left: -$length; + border-top: 2px solid $border-color; + width: $length; + height: 1px; + } +} + +@mixin build-content($border-radius: 30px) { + display: inline-block; + padding: 8px 10px 9px; + width: 100%; + border: 1px solid $border-color; + border-radius: $border-radius; + background-color: $white-light; + + &:hover { + background-color: $stage-hover-bg; + border: 1px solid $dropdown-toggle-active-border-color; + color: $gl-text-color; + } +} + .pipelines { .stage { max-width: 90px; @@ -357,14 +384,8 @@ &:not(:first-child) { margin-left: 44px; - .left-connector::before { - content: ''; - position: absolute; - top: 48%; - left: -44px; - border-top: 2px solid $border-color; - width: 44px; - height: 1px; + .left-connector { + @include flat-connector-before; } } } @@ -479,12 +500,7 @@ } .build-content { - display: inline-block; - padding: 8px 10px 9px; - width: 100%; - border: 1px solid $border-color; - border-radius: 30px; - background-color: $white-light; + @include build-content(); } a.build-content:hover, @@ -622,8 +638,7 @@ } } -// Dropdown button in mini pipeline graph -button.mini-pipeline-graph-dropdown-toggle { +@mixin mini-pipeline-item() { border-radius: 100px; background-color: $white-light; border-width: 1px; @@ -636,30 +651,6 @@ button.mini-pipeline-graph-dropdown-toggle { position: relative; vertical-align: middle; - > .fa.fa-caret-down { - position: absolute; - left: 20px; - top: 5px; - display: inline-block; - visibility: hidden; - opacity: 0; - color: inherit; - font-size: 12px; - transition: visibility 0.1s, opacity 0.1s linear; - } - - &:active, - &:focus, - &:hover { - outline: none; - width: 35px; - - .fa.fa-caret-down { - visibility: visible; - opacity: 1; - } - } - // Dropdown button animation in mini pipeline graph &.ci-status-icon-success { @include mini-pipeline-graph-color($green-100, $green-500, $green-600); @@ -691,6 +682,35 @@ button.mini-pipeline-graph-dropdown-toggle { } } +// Dropdown button in mini pipeline graph +button.mini-pipeline-graph-dropdown-toggle { + @include mini-pipeline-item(); + + > .fa.fa-caret-down { + position: absolute; + left: 20px; + top: 5px; + display: inline-block; + visibility: hidden; + opacity: 0; + color: inherit; + font-size: 12px; + transition: visibility 0.1s, opacity 0.1s linear; + } + + &:active, + &:focus, + &:hover { + outline: none; + width: 35px; + + .fa.fa-caret-down { + visibility: visible; + opacity: 1; + } + } +} + /** Action icons inside dropdowns: - mini graph in pipelines table @@ -744,7 +764,7 @@ button.mini-pipeline-graph-dropdown-toggle { } } - // SVGs in the commit widget and mr widget + // SVGs in the commit widget and mr widget a.ci-action-icon-container.ci-action-icon-wrapper svg { top: 2px; } -- cgit v1.2.1 From 5d2d278919a926e37a1a640368f64eeff13d75de Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 25 May 2018 10:16:17 -0500 Subject: Simplify users API QA spec --- qa/qa/specs/features/api/users_spec.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/qa/qa/specs/features/api/users_spec.rb b/qa/qa/specs/features/api/users_spec.rb index d4ff4ebbc9a..38f4c497183 100644 --- a/qa/qa/specs/features/api/users_spec.rb +++ b/qa/qa/specs/features/api/users_spec.rb @@ -17,17 +17,16 @@ module QA get request.url, { params: { username: Runtime::User.name } } expect_status(200) - expect(json_body).to be_an Array - expect(json_body.size).to eq(1) - expect(json_body.first[:username]).to eq Runtime::User.name + expect(json_body).to contain_exactly( + a_hash_including(username: Runtime::User.name) + ) end scenario 'submit request with an invalid user name' do get request.url, { params: { username: SecureRandom.hex(10) } } expect_status(200) - expect(json_body).to be_an Array - expect(json_body.size).to eq(0) + expect(json_body).to eq([]) end end -- cgit v1.2.1 From dc9ef9ed122a8367cf04b54025a0335e4702a2b0 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Fri, 25 May 2018 16:27:24 -0700 Subject: Fix branches panel at smaller screen sizes --- app/assets/stylesheets/bootstrap_migration.scss | 4 ++++ app/views/projects/branches/_branch.html.haml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/bootstrap_migration.scss b/app/assets/stylesheets/bootstrap_migration.scss index 3b7ee5c73e6..2f3e14bb6c5 100644 --- a/app/assets/stylesheets/bootstrap_migration.scss +++ b/app/assets/stylesheets/bootstrap_migration.scss @@ -131,6 +131,10 @@ table { } .card { + .card-title { + margin-bottom: 0; + } + &.card-without-border { @extend .border-0; } diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 5b1f2d8953b..f641d7bc51a 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -28,7 +28,7 @@ = s_('Branches|Cant find HEAD commit for this branch') - if branch.name != @repository.root_ref - .divergence-graph.d-none.d-sm-block{ title: s_('%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead') % { number_commits_behind: diverging_count_label(number_commits_behind), + .divergence-graph.d-none.d-md-block{ title: s_('%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead') % { number_commits_behind: diverging_count_label(number_commits_behind), default_branch: @repository.root_ref, number_commits_ahead: diverging_count_label(number_commits_ahead) } } .graph-side @@ -39,7 +39,7 @@ .bar.bar-ahead{ style: "width: #{number_commits_ahead * bar_graph_width_factor}%" } %span.count.count-ahead= diverging_count_label(number_commits_ahead) - .controls.d-none.d-sm-block< + .controls.d-none.d-md-block< - if merge_project && create_mr_button?(@repository.root_ref, branch.name) = link_to create_mr_path(@repository.root_ref, branch.name), class: 'btn btn-default' do = _('Merge request') -- cgit v1.2.1 From b6125f7045d2bed4aadf798dde4c547e2047e039 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 25 May 2018 14:28:16 -0700 Subject: Fix fast admin counters not working when PostgreSQL has secondaries This commit does a number of things: 1. Reduces the number of queries needed by perform a single query to get all the tuples for the relevant rows. 2. Uses a transaction to query the tuple counts to ensure that the data is retrieved from the primary. Closes #46742 --- app/controllers/admin/dashboard_controller.rb | 4 ++ app/helpers/count_helper.rb | 8 ++- app/views/admin/dashboard/index.html.haml | 20 +++--- .../unreleased/sh-fix-admin-page-counts-take-2.yml | 5 ++ lib/gitlab/database/count.rb | 72 ++++++++++++++----- spec/lib/gitlab/database/count_spec.rb | 81 ++++++++++++---------- spec/views/admin/dashboard/index.html.haml_spec.rb | 5 ++ 7 files changed, 130 insertions(+), 65 deletions(-) create mode 100644 changelogs/unreleased/sh-fix-admin-page-counts-take-2.yml diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb index d6a6bc7d4a1..737942f3eb2 100644 --- a/app/controllers/admin/dashboard_controller.rb +++ b/app/controllers/admin/dashboard_controller.rb @@ -1,7 +1,11 @@ class Admin::DashboardController < Admin::ApplicationController include CountHelper + COUNTED_ITEMS = [Project, User, Group, ForkedProjectLink, Issue, MergeRequest, + Note, Snippet, Key, Milestone].freeze + def index + @counts = Gitlab::Database::Count.approximate_counts(COUNTED_ITEMS) @projects = Project.order_id_desc.without_deleted.with_route.limit(10) @users = User.order_id_desc.limit(10) @groups = Group.order_id_desc.with_route.limit(10) diff --git a/app/helpers/count_helper.rb b/app/helpers/count_helper.rb index 24ee62e68ba..5cd98f40f78 100644 --- a/app/helpers/count_helper.rb +++ b/app/helpers/count_helper.rb @@ -1,5 +1,9 @@ module CountHelper - def approximate_count_with_delimiters(model) - number_with_delimiter(Gitlab::Database::Count.approximate_count(model)) + def approximate_count_with_delimiters(count_data, model) + count = count_data[model] + + raise "Missing model #{model} from count data" unless count + + number_with_delimiter(count) end end diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index 3df4ce93fa8..3cdeb103bb8 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -12,7 +12,7 @@ = link_to admin_projects_path do %h3.text-center Projects: - = approximate_count_with_delimiters(Project) + = approximate_count_with_delimiters(@counts, Project) %hr = link_to('New project', new_project_path, class: "btn btn-new") .col-sm-4 @@ -21,7 +21,7 @@ = link_to admin_users_path do %h3.text-center Users: - = approximate_count_with_delimiters(User) + = approximate_count_with_delimiters(@counts, User) = render_if_exists 'users_statistics' %hr = link_to 'New user', new_admin_user_path, class: "btn btn-new" @@ -31,7 +31,7 @@ = link_to admin_groups_path do %h3.text-center Groups: - = approximate_count_with_delimiters(Group) + = approximate_count_with_delimiters(@counts, Group) %hr = link_to 'New group', new_admin_group_path, class: "btn btn-new" .row @@ -42,31 +42,31 @@ %p Forks %span.light.float-right - = approximate_count_with_delimiters(ForkedProjectLink) + = approximate_count_with_delimiters(@counts, ForkedProjectLink) %p Issues %span.light.float-right - = approximate_count_with_delimiters(Issue) + = approximate_count_with_delimiters(@counts, Issue) %p Merge Requests %span.light.float-right - = approximate_count_with_delimiters(MergeRequest) + = approximate_count_with_delimiters(@counts, MergeRequest) %p Notes %span.light.float-right - = approximate_count_with_delimiters(Note) + = approximate_count_with_delimiters(@counts, Note) %p Snippets %span.light.float-right - = approximate_count_with_delimiters(Snippet) + = approximate_count_with_delimiters(@counts, Snippet) %p SSH Keys %span.light.float-right - = approximate_count_with_delimiters(Key) + = approximate_count_with_delimiters(@counts, Key) %p Milestones %span.light.float-right - = approximate_count_with_delimiters(Milestone) + = approximate_count_with_delimiters(@counts, Milestone) %p Active Users %span.light.float-right diff --git a/changelogs/unreleased/sh-fix-admin-page-counts-take-2.yml b/changelogs/unreleased/sh-fix-admin-page-counts-take-2.yml new file mode 100644 index 00000000000..d9bd1af9380 --- /dev/null +++ b/changelogs/unreleased/sh-fix-admin-page-counts-take-2.yml @@ -0,0 +1,5 @@ +--- +title: Fix admin counters not working when PostgreSQL has secondaries +merge_request: +author: +type: fixed diff --git a/lib/gitlab/database/count.rb b/lib/gitlab/database/count.rb index 3374203960e..5f549ed2b3c 100644 --- a/lib/gitlab/database/count.rb +++ b/lib/gitlab/database/count.rb @@ -17,31 +17,69 @@ module Gitlab ].freeze end - def self.approximate_count(model) - return model.count unless Gitlab::Database.postgresql? + # Takes in an array of models and returns a Hash for the approximate + # counts for them. If the model's table has not been vacuumed or + # analyzed recently, simply run the Model.count to get the data. + # + # @param [Array] + # @return [Hash] of Model -> count mapping + def self.approximate_counts(models) + table_to_model_map = models.each_with_object({}) do |model, hash| + hash[model.table_name] = model + end - execute_estimate_if_updated_recently(model) || model.count - end + table_names = table_to_model_map.keys + counts_by_table_name = Gitlab::Database.postgresql? ? reltuples_from_recently_updated(table_names) : {} - def self.execute_estimate_if_updated_recently(model) - ActiveRecord::Base.connection.select_value(postgresql_estimate_query(model)).to_i if reltuples_updated_recently?(model) - rescue *CONNECTION_ERRORS + # Convert table -> count to Model -> count + counts_by_model = counts_by_table_name.each_with_object({}) do |pair, hash| + model = table_to_model_map[pair.first] + hash[model] = pair.second + end + + missing_tables = table_names - counts_by_table_name.keys + + missing_tables.each do |table| + model = table_to_model_map[table] + counts_by_model[model] = model.count + end + + counts_by_model end - def self.reltuples_updated_recently?(model) - time = "to_timestamp(#{1.hour.ago.to_i})" - query = <<~SQL - SELECT 1 FROM pg_stat_user_tables WHERE relname = '#{model.table_name}' AND - (last_vacuum > #{time} OR last_autovacuum > #{time} OR last_analyze > #{time} OR last_autoanalyze > #{time}) - SQL + # Returns a hash of the table names that have recently updated tuples. + # + # @param [Array] table names + # @returns [Hash] Table name to count mapping (e.g. { 'projects' => 5, 'users' => 100 }) + def self.reltuples_from_recently_updated(table_names) + query = postgresql_estimate_query(table_names) + rows = [] - ActiveRecord::Base.connection.select_all(query).count > 0 + # Querying tuple stats only works on the primary. Due to load + # balancing, we need to ensure this query hits the load balancer. The + # easiest way to do this is to start a transaction. + ActiveRecord::Base.transaction do + rows = ActiveRecord::Base.connection.select_all(query) + end + + rows.each_with_object({}) { |row, data| data[row['table_name']] = row['estimate'].to_i } rescue *CONNECTION_ERRORS - false + {} end - def self.postgresql_estimate_query(model) - "SELECT reltuples::bigint AS estimate FROM pg_class where relname = '#{model.table_name}'" + # Generates the PostgreSQL query to return the tuples for tables + # that have been vacuumed or analyzed in the last hour. + # + # @param [Array] table names + # @returns [Hash] Table name to count mapping (e.g. { 'projects' => 5, 'users' => 100 }) + def self.postgresql_estimate_query(table_names) + time = "to_timestamp(#{1.hour.ago.to_i})" + <<~SQL + SELECT pg_class.relname AS table_name, reltuples::bigint AS estimate FROM pg_class + LEFT JOIN pg_stat_user_tables ON pg_class.relname = pg_stat_user_tables.relname + WHERE pg_class.relname IN (#{table_names.map { |table| "'#{table}'" }.join(',')}) + AND (last_vacuum > #{time} OR last_autovacuum > #{time} OR last_analyze > #{time} OR last_autoanalyze > #{time}) + SQL end end end diff --git a/spec/lib/gitlab/database/count_spec.rb b/spec/lib/gitlab/database/count_spec.rb index 9d9caaabe16..407d9470785 100644 --- a/spec/lib/gitlab/database/count_spec.rb +++ b/spec/lib/gitlab/database/count_spec.rb @@ -3,59 +3,68 @@ require 'spec_helper' describe Gitlab::Database::Count do before do create_list(:project, 3) + create(:identity) end - describe '.execute_estimate_if_updated_recently', :postgresql do - context 'when reltuples have not been updated' do - before do - expect(described_class).to receive(:reltuples_updated_recently?).and_return(false) - end + let(:models) { [Project, Identity] } - it 'returns nil' do - expect(described_class.execute_estimate_if_updated_recently(Project)).to be nil - end - end + describe '.approximate_counts' do + context 'with MySQL' do + context 'when reltuples have not been updated' do + it 'counts all models the normal way' do + expect(Gitlab::Database).to receive(:postgresql?).and_return(false) - context 'when reltuples have been updated' do - before do - ActiveRecord::Base.connection.execute('ANALYZE projects') - end + expect(Project).to receive(:count).and_call_original + expect(Identity).to receive(:count).and_call_original - it 'calls postgresql_estimate_query' do - expect(described_class).to receive(:postgresql_estimate_query).with(Project).and_call_original - expect(described_class.execute_estimate_if_updated_recently(Project)).to eq(3) + expect(described_class.approximate_counts(models)).to eq({ Project => 3, Identity => 1 }) + end end end - end - describe '.approximate_count' do - context 'when reltuples have not been updated' do - it 'counts all projects the normal way' do - allow(described_class).to receive(:reltuples_updated_recently?).and_return(false) + context 'with PostgreSQL', :postgresql do + describe 'when reltuples have not been updated' do + it 'counts all models the normal way' do + expect(described_class).to receive(:reltuples_from_recently_updated).with(%w(projects identities)).and_return({}) - expect(Project).to receive(:count).and_call_original - expect(described_class.approximate_count(Project)).to eq(3) + expect(Project).to receive(:count).and_call_original + expect(Identity).to receive(:count).and_call_original + expect(described_class.approximate_counts(models)).to eq({ Project => 3, Identity => 1 }) + end end - end - context 'no permission' do - it 'falls back to standard query' do - allow(described_class).to receive(:reltuples_updated_recently?).and_raise(PG::InsufficientPrivilege) + describe 'no permission' do + it 'falls back to standard query' do + allow(described_class).to receive(:postgresql_estimate_query).and_raise(PG::InsufficientPrivilege) - expect(Project).to receive(:count).and_call_original - expect(described_class.approximate_count(Project)).to eq(3) + expect(Project).to receive(:count).and_call_original + expect(Identity).to receive(:count).and_call_original + expect(described_class.approximate_counts(models)).to eq({ Project => 3, Identity => 1 }) + end end - end - describe 'when reltuples have been updated', :postgresql do - before do - ActiveRecord::Base.connection.execute('ANALYZE projects') + describe 'when some reltuples have been updated' do + it 'counts projects in the fast way' do + expect(described_class).to receive(:reltuples_from_recently_updated).with(%w(projects identities)).and_return({ 'projects' => 3 }) + + expect(Project).not_to receive(:count).and_call_original + expect(Identity).to receive(:count).and_call_original + expect(described_class.approximate_counts(models)).to eq({ Project => 3, Identity => 1 }) + end end - it 'counts all projects in the fast way' do - expect(described_class).to receive(:postgresql_estimate_query).with(Project).and_call_original + describe 'when all reltuples have been updated' do + before do + ActiveRecord::Base.connection.execute('ANALYZE projects') + ActiveRecord::Base.connection.execute('ANALYZE identities') + end + + it 'counts models with the standard way' do + expect(Project).not_to receive(:count) + expect(Identity).not_to receive(:count) - expect(described_class.approximate_count(Project)).to eq(3) + expect(described_class.approximate_counts(models)).to eq({ Project => 3, Identity => 1 }) + end end end end diff --git a/spec/views/admin/dashboard/index.html.haml_spec.rb b/spec/views/admin/dashboard/index.html.haml_spec.rb index 59c777ea338..0e8b7c82d3a 100644 --- a/spec/views/admin/dashboard/index.html.haml_spec.rb +++ b/spec/views/admin/dashboard/index.html.haml_spec.rb @@ -4,6 +4,11 @@ describe 'admin/dashboard/index.html.haml' do include Devise::Test::ControllerHelpers before do + counts = Admin::DashboardController::COUNTED_ITEMS.each_with_object({}) do |item, hash| + hash[item] = 100 + end + + assign(:counts, counts) assign(:projects, create_list(:project, 1)) assign(:users, create_list(:user, 1)) assign(:groups, create_list(:group, 1)) -- cgit v1.2.1 From 4131a49bb72ab62c9384050d90ec268b4f3d76aa Mon Sep 17 00:00:00 2001 From: Semyon Pupkov Date: Thu, 10 May 2018 12:58:19 +0500 Subject: Expose artifacts_expire_at field for job entity in api https://gitlab.com/gitlab-org/gitlab-ce/issues/45798 --- changelogs/unreleased/add-artifacts_expire_at-to-api.yml | 5 +++++ doc/api/jobs.md | 5 +++++ lib/api/entities.rb | 1 + spec/requests/api/jobs_spec.rb | 8 +++++++- 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/add-artifacts_expire_at-to-api.yml diff --git a/changelogs/unreleased/add-artifacts_expire_at-to-api.yml b/changelogs/unreleased/add-artifacts_expire_at-to-api.yml new file mode 100644 index 00000000000..7fe0d8b5720 --- /dev/null +++ b/changelogs/unreleased/add-artifacts_expire_at-to-api.yml @@ -0,0 +1,5 @@ +--- +title: Expose artifacts_expire_at field for job entity in api +merge_request: 18872 +author: Semyon Pupkov +type: added diff --git a/doc/api/jobs.md b/doc/api/jobs.md index e4e48edd9a7..0fbfc7cf0fd 100644 --- a/doc/api/jobs.md +++ b/doc/api/jobs.md @@ -38,6 +38,7 @@ Example of response "size": 1000 }, "finished_at": "2015-12-24T17:54:27.895Z", + "artifacts_expire_at": "2016-01-23T17:54:27.895Z" "id": 7, "name": "teaspoon", "pipeline": { @@ -81,6 +82,7 @@ Example of response "created_at": "2015-12-24T15:51:21.727Z", "artifacts_file": null, "finished_at": "2015-12-24T17:54:24.921Z", + "artifacts_expire_at": "2016-01-23T17:54:24.921Z", "id": 6, "name": "rspec:other", "pipeline": { @@ -152,6 +154,7 @@ Example of response "size": 1000 }, "finished_at": "2015-12-24T17:54:27.895Z", + "artifacts_expire_at": "2016-01-23T17:54:27.895Z" "id": 7, "name": "teaspoon", "pipeline": { @@ -195,6 +198,7 @@ Example of response "created_at": "2015-12-24T15:51:21.727Z", "artifacts_file": null, "finished_at": "2015-12-24T17:54:24.921Z", + "artifacts_expire_at": "2016-01-23T17:54:24.921Z" "id": 6, "name": "rspec:other", "pipeline": { @@ -261,6 +265,7 @@ Example of response "created_at": "2015-12-24T15:51:21.880Z", "artifacts_file": null, "finished_at": "2015-12-24T17:54:31.198Z", + "artifacts_expire_at": "2016-01-23T17:54:31.198Z", "id": 8, "name": "rubocop", "pipeline": { diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 174c5af91d5..3e615f7ac05 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -1020,6 +1020,7 @@ module API class Job < JobBasic expose :artifacts_file, using: JobArtifactFile, if: -> (job, opts) { job.artifacts? } expose :runner, with: Runner + expose :artifacts_expire_at end class JobBasicWithProject < JobBasic diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb index 0a2963452e4..45082e644ca 100644 --- a/spec/requests/api/jobs_spec.rb +++ b/spec/requests/api/jobs_spec.rb @@ -13,7 +13,10 @@ describe API::Jobs do ref: project.default_branch) end - let!(:job) { create(:ci_build, :success, pipeline: pipeline) } + let!(:job) do + create(:ci_build, :success, pipeline: pipeline, + artifacts_expire_at: 1.day.since) + end let(:user) { create(:user) } let(:api_user) { user } @@ -43,6 +46,7 @@ describe API::Jobs do it 'returns correct values' do expect(json_response).not_to be_empty expect(json_response.first['commit']['id']).to eq project.commit.id + expect(Time.parse(json_response.first['artifacts_expire_at'])).to be_like_time(job.artifacts_expire_at) end it 'returns pipeline data' do @@ -128,6 +132,7 @@ describe API::Jobs do it 'returns correct values' do expect(json_response).not_to be_empty expect(json_response.first['commit']['id']).to eq project.commit.id + expect(Time.parse(json_response.first['artifacts_expire_at'])).to be_like_time(job.artifacts_expire_at) end it 'returns pipeline data' do @@ -201,6 +206,7 @@ describe API::Jobs do expect(Time.parse(json_response['created_at'])).to be_like_time(job.created_at) expect(Time.parse(json_response['started_at'])).to be_like_time(job.started_at) expect(Time.parse(json_response['finished_at'])).to be_like_time(job.finished_at) + expect(Time.parse(json_response['artifacts_expire_at'])).to be_like_time(job.artifacts_expire_at) expect(json_response['duration']).to eq(job.duration) end -- cgit v1.2.1 From 6123e1db830de0d753228f4d3a44e95ff6d0f393 Mon Sep 17 00:00:00 2001 From: Takuya Noguchi Date: Sat, 26 May 2018 23:35:48 +0900 Subject: Update redis-namespace to 1.6.0 --- Gemfile | 2 +- Gemfile.lock | 6 +++--- changelogs/unreleased/46846-update-redis-namespace-to-1-6-0.yml | 5 +++++ 3 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 changelogs/unreleased/46846-update-redis-namespace-to-1-6-0.yml diff --git a/Gemfile b/Gemfile index cc0758f7c57..e48c1f47d21 100644 --- a/Gemfile +++ b/Gemfile @@ -162,7 +162,7 @@ gem 'acts-as-taggable-on', '~> 5.0' # Background jobs gem 'sidekiq', '~> 5.1' gem 'sidekiq-cron', '~> 0.6.0' -gem 'redis-namespace', '~> 1.5.2' +gem 'redis-namespace', '~> 1.6.0' gem 'sidekiq-limit_fetch', '~> 3.4', require: false # Cron Parser diff --git a/Gemfile.lock b/Gemfile.lock index 7332b55c175..5613c89a0ae 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -709,8 +709,8 @@ GEM redis-activesupport (5.0.4) activesupport (>= 3, < 6) redis-store (>= 1.3, < 2) - redis-namespace (1.5.2) - redis (~> 3.0, >= 3.0.4) + redis-namespace (1.6.0) + redis (>= 3.0.4) redis-rack (2.0.4) rack (>= 1.5, < 3) redis-store (>= 1.2, < 2) @@ -1129,7 +1129,7 @@ DEPENDENCIES recaptcha (~> 3.0) redcarpet (~> 3.4) redis (~> 3.2) - redis-namespace (~> 1.5.2) + redis-namespace (~> 1.6.0) redis-rails (~> 5.0.2) request_store (~> 1.3) responders (~> 2.0) diff --git a/changelogs/unreleased/46846-update-redis-namespace-to-1-6-0.yml b/changelogs/unreleased/46846-update-redis-namespace-to-1-6-0.yml new file mode 100644 index 00000000000..3707ad74b8f --- /dev/null +++ b/changelogs/unreleased/46846-update-redis-namespace-to-1-6-0.yml @@ -0,0 +1,5 @@ +--- +title: Update redis-namespace to 1.6.0 +merge_request: 19166 +author: Takuya Noguchi +type: other -- cgit v1.2.1 From 2476801b0c74f99cdf806a11108d8082f6509f50 Mon Sep 17 00:00:00 2001 From: Takuya Noguchi Date: Sun, 27 May 2018 01:30:24 +0900 Subject: Update rdoc to 6.0.4 --- Gemfile | 2 +- Gemfile.lock | 5 ++--- changelogs/unreleased/46849-update-rdoc-to-6-0-4.yml | 5 +++++ 3 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 changelogs/unreleased/46849-update-rdoc-to-6-0-4.yml diff --git a/Gemfile b/Gemfile index cc0758f7c57..5650b86cd0b 100644 --- a/Gemfile +++ b/Gemfile @@ -133,7 +133,7 @@ gem 'gitlab-markup', '~> 1.6.2' gem 'redcarpet', '~> 3.4' gem 'commonmarker', '~> 0.17' gem 'RedCloth', '~> 4.3.2' -gem 'rdoc', '~> 4.2' +gem 'rdoc', '~> 6.0' gem 'org-ruby', '~> 0.9.12' gem 'creole', '~> 0.5.0' gem 'wikicloth', '0.8.1' diff --git a/Gemfile.lock b/Gemfile.lock index 7332b55c175..1c2a5509d3e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -694,8 +694,7 @@ GEM ffi rbnacl-libsodium (1.0.11) rbnacl (>= 3.0.1) - rdoc (4.2.2) - json (~> 1.4) + rdoc (6.0.4) re2 (1.1.1) recaptcha (3.0.0) json @@ -1124,7 +1123,7 @@ DEPENDENCIES rblineprof (~> 0.3.6) rbnacl (~> 4.0) rbnacl-libsodium - rdoc (~> 4.2) + rdoc (~> 6.0) re2 (~> 1.1.1) recaptcha (~> 3.0) redcarpet (~> 3.4) diff --git a/changelogs/unreleased/46849-update-rdoc-to-6-0-4.yml b/changelogs/unreleased/46849-update-rdoc-to-6-0-4.yml new file mode 100644 index 00000000000..cf0436df1a7 --- /dev/null +++ b/changelogs/unreleased/46849-update-rdoc-to-6-0-4.yml @@ -0,0 +1,5 @@ +--- +title: Update rdoc to 6.0.4 +merge_request: 19167 +author: Takuya Noguchi +type: other -- cgit v1.2.1 From 1637faacbafb8507c7107d2f6775dcb4dba35778 Mon Sep 17 00:00:00 2001 From: Lukas Eipert Date: Sun, 27 May 2018 17:45:12 +0200 Subject: Update unicode-display_width from 1.3.0 to 1.3.2 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 7332b55c175..537c377dccc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -918,7 +918,7 @@ GEM unf (0.1.4) unf_ext unf_ext (0.0.7.5) - unicode-display_width (1.3.0) + unicode-display_width (1.3.2) unicorn (5.1.0) kgio (~> 2.6) raindrops (~> 0.7) -- cgit v1.2.1 From 8f57de8188adff4f1160f64342c267f2ba1fc725 Mon Sep 17 00:00:00 2001 From: Lukas Eipert Date: Sun, 27 May 2018 19:21:12 +0000 Subject: Update Frontend documentation regarding Vue and Icons/Illustrations --- doc/development/fe_guide/icons.md | 114 +++++++++++++++++------ doc/development/fe_guide/index.md | 4 +- doc/development/fe_guide/vue.md | 190 +++++++++++++++++--------------------- 3 files changed, 173 insertions(+), 135 deletions(-) diff --git a/doc/development/fe_guide/icons.md b/doc/development/fe_guide/icons.md index b469a9c6aef..3d8da6accc1 100644 --- a/doc/development/fe_guide/icons.md +++ b/doc/development/fe_guide/icons.md @@ -1,26 +1,44 @@ -# Icons +# Icons and SVG Illustrations -We are using SVG Icons in GitLab with a SVG Sprite, due to this the icons are only loaded once and then referenced through an ID. The sprite SVG is located under `/assets/icons.svg`. Our goal is to replace one by one all inline SVG Icons (as those currently bloat the HTML) and also all Font Awesome usages. +We manage our own Icon and Illustration library in the [gitlab-svgs][gitlab-svgs] repository. +This repository is published on [npm][npm] and managed as a dependency via yarn. +You can browse all available Icons and Illustrations [here][svg-preview]. +To upgrade to a new version run `yarn upgrade @gitlab-org/gitlab-svgs`. -### Usage in HAML/Rails +## Icons -To use a sprite Icon in HAML or Rails we use a specific helper function : +We are using SVG Icons in GitLab with a SVG Sprite. +This means the icons are only loaded once, and are referenced through an ID. +The sprite SVG is located under `/assets/icons.svg`. + +Our goal is to replace one by one all inline SVG Icons (as those currently bloat the HTML) and also all Font Awesome icons. -`sprite_icon(icon_name, size: nil, css_class: '')` +### Usage in HAML/Rails -**icon_name** Use the icon_name that you can find in the SVG Sprite ([Overview is available here](http://gitlab-org.gitlab.io/gitlab-svgs/)`). +To use a sprite Icon in HAML or Rails we use a specific helper function : -**size (optional)** Use one of the following sizes : 16,24,32,48,72 (this will be translated into a `s16` class) +```ruby +sprite_icon(icon_name, size: nil, css_class: '') +``` -**css_class (optional)** If you want to add additional css classes +- **icon_name** Use the icon_name that you can find in the SVG Sprite + ([Overview is available here][svg-preview]). +- **size (optional)** Use one of the following sizes : 16, 24, 32, 48, 72 (this will be translated into a `s16` class) +- **css_class (optional)** If you want to add additional css classes **Example** -`= sprite_icon('issues', size: 72, css_class: 'icon-danger')` +```haml += sprite_icon('issues', size: 72, css_class: 'icon-danger') +``` **Output from example above** -`` +```html + + + +``` ### Usage in Vue @@ -28,33 +46,71 @@ We have a special Vue component for our sprite icons in `\vue_shared\components\ Sample usage : -`` - -**name** Name of the Icon in the SVG Sprite ([Overview is available here](http://gitlab-org.gitlab.io/gitlab-svgs/)`). - -**size (optional)** Number value for the size which is then mapped to a specific CSS class (Available Sizes: 8,12,16,18,24,32,48,72 are mapped to `sXX` css classes) - -**css-classes (optional)** Additional CSS Classes to add to the svg tag. +```javascript + diff --git a/app/assets/stylesheets/pages/repo.scss b/app/assets/stylesheets/pages/repo.scss index 17d7087bd85..2cb1af7896b 100644 --- a/app/assets/stylesheets/pages/repo.scss +++ b/app/assets/stylesheets/pages/repo.scss @@ -1088,10 +1088,6 @@ font-size: 12px; } -.ide-new-modal-label { - line-height: 34px; -} - .multi-file-commit-panel-success-message { position: absolute; top: 61px; -- cgit v1.2.1 From c0f3bd92a775afd1eb92943bfeccee7706e00ac5 Mon Sep 17 00:00:00 2001 From: Lukas Eipert Date: Mon, 28 May 2018 10:54:38 +0200 Subject: convert eslintrc to yml --- .eslintrc | 56 -------------------------------------------------------- .eslintrc.yml | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 56 deletions(-) delete mode 100644 .eslintrc create mode 100644 .eslintrc.yml diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 3f187db0c07..00000000000 --- a/.eslintrc +++ /dev/null @@ -1,56 +0,0 @@ -{ - "env": { - "browser": true, - "es6": true - }, - "extends": [ - "airbnb-base", - "plugin:vue/recommended" - ], - "globals": { - "__webpack_public_path__": true, - "gl": false, - "gon": false, - "localStorage": false - }, - "parserOptions": { - "parser": "babel-eslint" - }, - "plugins": [ - "filenames", - "import", - "html", - "promise" - ], - "settings": { - "html/html-extensions": [".html", ".html.raw"], - "import/resolver": { - "webpack": { - "config": "./config/webpack.config.js" - } - } - }, - "rules": { - "filenames/match-regex": [2, "^[a-z0-9_]+$"], - "import/no-commonjs": "error", - "no-multiple-empty-lines": ["error", { "max": 1 }], - "promise/catch-or-return": "error", - "no-underscore-dangle": ["error", { "allow": ["__", "_links"] }], - "no-mixed-operators": 0, - "space-before-function-paren": 0, - "curly": 0, - "arrow-parens": 0, - "vue/html-self-closing": [ - "error", - { - "html": { - "void": "always", - "normal": "never", - "component": "always" - }, - "svg": "always", - "math": "always" - } - ] - } -} diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 00000000000..ceacf23f19c --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,53 @@ +--- +env: + browser: true + es6: true +extends: + - airbnb-base + - plugin:vue/recommended +globals: + __webpack_public_path__: true + gl: false + gon: false + localStorage: false +parserOptions: + parser: babel-eslint +plugins: + - filenames + - import + - html + - promise +settings: + html/html-extensions: + - ".html" + - ".html.raw" + import/resolver: + webpack: + config: "./config/webpack.config.js" +rules: + filenames/match-regex: + - error + - "^[a-z0-9_]+$" + import/no-commonjs: error + no-multiple-empty-lines: + - error + - max: 1 + promise/catch-or-return: error + no-underscore-dangle: + - error + - allow: + - __ + - _links + no-mixed-operators: 0 + vue/html-self-closing: + - error + - html: + void: always + normal: never + component: always + svg: always + math: always + ## Conflicting rules with prettier: + space-before-function-paren: 0 + curly: 0 + arrow-parens: 0 -- cgit v1.2.1 From 2858ea8cd622156ee96c6d65d23d4f31c25446ba Mon Sep 17 00:00:00 2001 From: Lukas Eipert Date: Tue, 29 May 2018 18:41:29 +0200 Subject: Upgrade to eslint `~4.12.1` which is the last known version where the camelcase bug does not persist --- app/assets/javascripts/raven/raven_config.js | 2 +- package.json | 16 +- yarn.lock | 834 ++++++++++++--------------- 3 files changed, 366 insertions(+), 486 deletions(-) diff --git a/app/assets/javascripts/raven/raven_config.js b/app/assets/javascripts/raven/raven_config.js index ae54fa5f1a9..658caeecde1 100644 --- a/app/assets/javascripts/raven/raven_config.js +++ b/app/assets/javascripts/raven/raven_config.js @@ -37,7 +37,7 @@ const IGNORE_URLS = [ /extensions\//i, /^chrome:\/\//i, // Other plugins - /127\.0\.0\.1:4001\/isrunning/i, // Cacaoweb + /127\.0\.0\.1:4001\/isrunning/i, // Cacaoweb /webappstoolbarba\.texthelp\.com\//i, /metrics\.itunes\.apple\.com\.edgesuite\.net\//i, ]; diff --git a/package.json b/package.json index defcbd34d95..0113d49c8f2 100644 --- a/package.json +++ b/package.json @@ -100,21 +100,21 @@ }, "devDependencies": { "axios-mock-adapter": "^1.15.0", - "babel-eslint": "^8.0.2", + "babel-eslint": "^8.2.3", "babel-plugin-istanbul": "^4.1.6", "babel-plugin-rewire": "^1.1.0", "babel-template": "^6.26.0", "babel-types": "^6.26.0", "chalk": "^2.4.1", "commander": "^2.15.1", - "eslint": "^3.18.0", - "eslint-config-airbnb-base": "^10.0.1", - "eslint-import-resolver-webpack": "^0.8.3", - "eslint-plugin-filenames": "^1.1.0", - "eslint-plugin-html": "2.0.1", - "eslint-plugin-import": "^2.2.0", + "eslint": "~4.12.1", + "eslint-config-airbnb-base": "^12.1.0", + "eslint-import-resolver-webpack": "^0.10.0", + "eslint-plugin-filenames": "^1.2.0", + "eslint-plugin-html": "4.0.3", + "eslint-plugin-import": "^2.12.0", "eslint-plugin-jasmine": "^2.1.0", - "eslint-plugin-promise": "^3.5.0", + "eslint-plugin-promise": "^3.8.0", "eslint-plugin-vue": "^4.0.1", "ignore": "^3.3.7", "istanbul": "^0.4.5", diff --git a/yarn.lock b/yarn.lock index b5ff26c4016..76d59b8ff52 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,53 +2,77 @@ # yarn lockfile v1 -"@babel/code-frame@7.0.0-beta.32", "@babel/code-frame@^7.0.0-beta.31": - version "7.0.0-beta.32" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.32.tgz#04f231b8ec70370df830d9926ce0f5add074ec4c" +"@babel/code-frame@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz#2a02643368de80916162be70865c97774f3adbd9" dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^3.0.0" + "@babel/highlight" "7.0.0-beta.44" -"@babel/helper-function-name@7.0.0-beta.32": - version "7.0.0-beta.32" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.32.tgz#6161af4419f1b4e3ed2d28c0c79c160e218be1f3" +"@babel/generator@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.44.tgz#c7e67b9b5284afcf69b309b50d7d37f3e5033d42" dependencies: - "@babel/helper-get-function-arity" "7.0.0-beta.32" - "@babel/template" "7.0.0-beta.32" - "@babel/types" "7.0.0-beta.32" + "@babel/types" "7.0.0-beta.44" + jsesc "^2.5.1" + lodash "^4.2.0" + source-map "^0.5.0" + trim-right "^1.0.1" -"@babel/helper-get-function-arity@7.0.0-beta.32": - version "7.0.0-beta.32" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.32.tgz#93721a99db3757de575a83bab7c453299abca568" +"@babel/helper-function-name@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz#e18552aaae2231100a6e485e03854bc3532d44dd" dependencies: - "@babel/types" "7.0.0-beta.32" + "@babel/helper-get-function-arity" "7.0.0-beta.44" + "@babel/template" "7.0.0-beta.44" + "@babel/types" "7.0.0-beta.44" -"@babel/template@7.0.0-beta.32": - version "7.0.0-beta.32" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.32.tgz#e1d9fdbd2a7bcf128f2f920744a67dab18072495" +"@babel/helper-get-function-arity@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz#d03ca6dd2b9f7b0b1e6b32c56c72836140db3a15" dependencies: - "@babel/code-frame" "7.0.0-beta.32" - "@babel/types" "7.0.0-beta.32" - babylon "7.0.0-beta.32" - lodash "^4.2.0" + "@babel/types" "7.0.0-beta.44" -"@babel/traverse@^7.0.0-beta.31": - version "7.0.0-beta.32" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.32.tgz#b78b754c6e1af3360626183738e4c7a05951bc99" +"@babel/helper-split-export-declaration@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz#c0b351735e0fbcb3822c8ad8db4e583b05ebd9dc" dependencies: - "@babel/code-frame" "7.0.0-beta.32" - "@babel/helper-function-name" "7.0.0-beta.32" - "@babel/types" "7.0.0-beta.32" - babylon "7.0.0-beta.32" - debug "^3.0.1" - globals "^10.0.0" + "@babel/types" "7.0.0-beta.44" + +"@babel/highlight@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.44.tgz#18c94ce543916a80553edcdcf681890b200747d5" + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + +"@babel/template@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f" + dependencies: + "@babel/code-frame" "7.0.0-beta.44" + "@babel/types" "7.0.0-beta.44" + babylon "7.0.0-beta.44" + lodash "^4.2.0" + +"@babel/traverse@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.44.tgz#a970a2c45477ad18017e2e465a0606feee0d2966" + dependencies: + "@babel/code-frame" "7.0.0-beta.44" + "@babel/generator" "7.0.0-beta.44" + "@babel/helper-function-name" "7.0.0-beta.44" + "@babel/helper-split-export-declaration" "7.0.0-beta.44" + "@babel/types" "7.0.0-beta.44" + babylon "7.0.0-beta.44" + debug "^3.1.0" + globals "^11.1.0" invariant "^2.2.0" lodash "^4.2.0" -"@babel/types@7.0.0-beta.32", "@babel/types@^7.0.0-beta.31": - version "7.0.0-beta.32" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.32.tgz#c317d0ecc89297b80bbcb2f50608e31f6452a5ff" +"@babel/types@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.44.tgz#6b1b164591f77dec0a0342aca995f2d046b3a757" dependencies: esutils "^2.0.2" lodash "^4.2.0" @@ -118,9 +142,9 @@ acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" -acorn@^5.0.0, acorn@^5.2.1, acorn@^5.3.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.4.1.tgz#fdc58d9d17f4a4e98d102ded826a9b9759125102" +acorn@^5.0.0, acorn@^5.3.0, acorn@^5.5.0: + version "5.5.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9" addressparser@1.0.1: version "1.0.1" @@ -137,22 +161,22 @@ agent-base@2: extend "~3.0.0" semver "~5.0.1" -ajv-keywords@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" +ajv-keywords@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" ajv-keywords@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.1.0.tgz#ac2b27939c543e95d2c06e7f7f5c27be4aa543be" -ajv@^4.7.0, ajv@^4.9.1: +ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" dependencies: co "^4.6.0" json-stable-stringify "^1.0.1" -ajv@^5.1.0: +ajv@^5.1.0, ajv@^5.2.3, ajv@^5.3.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" dependencies: @@ -201,7 +225,7 @@ ansi-align@^2.0.0: dependencies: string-width "^2.0.0" -ansi-escapes@^1.0.0, ansi-escapes@^1.1.0: +ansi-escapes@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" @@ -467,7 +491,7 @@ axios@^0.17.1: follow-redirects "^1.2.5" is-buffer "^1.1.5" -babel-code-frame@^6.16.0, babel-code-frame@^6.26.0: +babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" dependencies: @@ -499,14 +523,16 @@ babel-core@^6.26.0, babel-core@^6.26.3: slash "^1.0.0" source-map "^0.5.7" -babel-eslint@^8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.0.2.tgz#e44fb9a037d749486071d52d65312f5c20aa7530" +babel-eslint@^8.2.3: + version "8.2.3" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.3.tgz#1a2e6681cc9bc4473c32899e59915e19cd6733cf" dependencies: - "@babel/code-frame" "^7.0.0-beta.31" - "@babel/traverse" "^7.0.0-beta.31" - "@babel/types" "^7.0.0-beta.31" - babylon "^7.0.0-beta.31" + "@babel/code-frame" "7.0.0-beta.44" + "@babel/traverse" "7.0.0-beta.44" + "@babel/types" "7.0.0-beta.44" + babylon "7.0.0-beta.44" + eslint-scope "~3.7.1" + eslint-visitor-keys "^1.0.0" babel-generator@^6.18.0, babel-generator@^6.26.0: version "6.26.0" @@ -1105,18 +1131,14 @@ babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26 lodash "^4.17.4" to-fast-properties "^1.0.3" -babylon@7.0.0-beta.32, babylon@^7.0.0-beta.31: - version "7.0.0-beta.32" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.32.tgz#e9033cb077f64d6895f4125968b37dc0a8c3bc6e" +babylon@7.0.0-beta.44, babylon@^7.0.0-beta.30: + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.44.tgz#89159e15e6e30c5096e22d738d8c0af8a0e8ca1d" babylon@^6.17.3, babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" -babylon@^7.0.0-beta.30: - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.44.tgz#89159e15e6e30c5096e22d738d8c0af8a0e8ca1d" - backo2@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" @@ -1378,11 +1400,11 @@ browserify-sign@^4.0.0: inherits "^2.0.1" parse-asn1 "^5.0.0" -browserify-zlib@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" dependencies: - pako "~0.2.0" + pako "~1.0.5" browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: version "1.7.7" @@ -1391,6 +1413,10 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: caniuse-db "^1.0.30000639" electron-to-chromium "^1.2.7" +buffer-from@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.0.0.tgz#4cb8832d23612589b0406e9e2956c17f06fdf531" + buffer-indexof@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.0.tgz#f54f647c4f4e25228baa656a2e57e43d5f270982" @@ -1423,7 +1449,7 @@ buildmail@4.0.1: nodemailer-shared "1.1.0" punycode "1.4.1" -builtin-modules@^1.0.0, builtin-modules@^1.1.1: +builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -1682,7 +1708,7 @@ cli-boxes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" -cli-cursor@^1.0.1, cli-cursor@^1.0.2: +cli-cursor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" dependencies: @@ -1906,10 +1932,11 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@^1.5.0, concat-stream@^1.5.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" +concat-stream@^1.5.0, concat-stream@^1.6.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" dependencies: + buffer-from "^1.0.0" inherits "^2.0.3" readable-stream "^2.2.2" typedarray "^0.0.6" @@ -2061,7 +2088,7 @@ cropper@^2.3.0: dependencies: jquery ">= 1.9.1" -cross-spawn@^5.0.1: +cross-spawn@^5.0.1, cross-spawn@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" dependencies: @@ -2314,18 +2341,6 @@ d3@3.5.17: version "3.5.17" resolved "https://registry.yarnpkg.com/d3/-/d3-3.5.17.tgz#bc46748004378b21a360c9fc7cf5231790762fb8" -d@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - dependencies: - es5-ext "^0.10.9" - -d@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/d/-/d-0.1.1.tgz#da184c535d18d8ee7ba2aa229b914009fae11309" - dependencies: - es5-ext "~0.10.2" - dagre-d3-renderer@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/dagre-d3-renderer/-/dagre-d3-renderer-0.4.24.tgz#b36ce2fe4ea20de43e7698627c6ede2a9f15ec45" @@ -2376,18 +2391,12 @@ de-indent@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" -debug@2, debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9, debug@~2.6.4, debug@~2.6.6: +debug@2, debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9, debug@~2.6.4, debug@~2.6.6: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: ms "2.0.0" -debug@2.2.0, debug@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" - dependencies: - ms "0.7.1" - debug@2.6.8: version "2.6.8" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" @@ -2400,6 +2409,12 @@ debug@^3.0.1, debug@^3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" +debug@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + dependencies: + ms "0.7.1" + decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -2593,12 +2608,11 @@ doctrine@1.5.0: esutils "^2.0.2" isarray "^1.0.0" -doctrine@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" +doctrine@^2.0.2: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" dependencies: esutils "^2.0.2" - isarray "^1.0.0" document-register-element@1.3.0: version "1.3.0" @@ -2848,62 +2862,10 @@ es-to-primitive@^1.1.1: is-date-object "^1.0.1" is-symbol "^1.0.1" -es5-ext@^0.10.14, es5-ext@^0.10.8, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2: - version "0.10.24" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.24.tgz#a55877c9924bc0c8d9bd3c2cbe17495ac1709b14" - dependencies: - es6-iterator "2" - es6-symbol "~3.1" - -es6-iterator@2, es6-iterator@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512" - dependencies: - d "1" - es5-ext "^0.10.14" - es6-symbol "^3.1" - -es6-map@^0.1.3: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-set "~0.1.5" - es6-symbol "~3.1.1" - event-emitter "~0.3.5" - es6-promise@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.0.2.tgz#010d5858423a5f118979665f46486a95c6ee2bb6" -es6-set@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-symbol "3.1.1" - event-emitter "~0.3.5" - -es6-symbol@3, es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@~3.1, es6-symbol@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - dependencies: - d "1" - es5-ext "~0.10.14" - -es6-weak-map@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.1.tgz#0d2bbd8827eb5fb4ba8f97fbfea50d43db21ea81" - dependencies: - d "^0.1.1" - es5-ext "^0.10.8" - es6-iterator "2" - es6-symbol "3" - escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -2934,86 +2896,78 @@ escodegen@1.x.x: optionalDependencies: source-map "~0.5.6" -escope@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" +eslint-config-airbnb-base@^12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-12.1.0.tgz#386441e54a12ccd957b0a92564a4bafebd747944" dependencies: - es6-map "^0.1.3" - es6-weak-map "^2.0.1" - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-config-airbnb-base@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-10.0.1.tgz#f17d4e52992c1d45d1b7713efbcd5ecd0e7e0506" + eslint-restricted-globals "^0.1.1" -eslint-import-resolver-node@^0.2.0: - version "0.2.3" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c" +eslint-import-resolver-node@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" dependencies: - debug "^2.2.0" - object-assign "^4.0.1" - resolve "^1.1.6" + debug "^2.6.9" + resolve "^1.5.0" -eslint-import-resolver-webpack@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.8.3.tgz#ad61e28df378a474459d953f246fd43f92675385" +eslint-import-resolver-webpack@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.10.0.tgz#b6f2468dc3e8b4ea076e5d75bece8da932789b07" dependencies: array-find "^1.0.0" debug "^2.6.8" enhanced-resolve "~0.9.0" - find-root "^0.1.1" + find-root "^1.1.0" has "^1.0.1" interpret "^1.0.0" - is-absolute "^0.2.3" - lodash.get "^3.7.0" - node-libs-browser "^1.0.0" - resolve "^1.2.0" + lodash "^4.17.4" + node-libs-browser "^1.0.0 || ^2.0.0" + resolve "^1.4.0" semver "^5.3.0" -eslint-module-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.0.0.tgz#a6f8c21d901358759cdc35dbac1982ae1ee58bce" +eslint-module-utils@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz#b270362cd88b1a48ad308976ce7fa54e98411746" dependencies: - debug "2.2.0" + debug "^2.6.8" pkg-dir "^1.0.0" -eslint-plugin-filenames@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-filenames/-/eslint-plugin-filenames-1.1.0.tgz#bb925218ab25b1aad1c622cfa9cb8f43cc03a4ff" +eslint-plugin-filenames@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-filenames/-/eslint-plugin-filenames-1.2.0.tgz#aee9c1c90189c95d2e49902c160eceefecd99f53" dependencies: - lodash.camelcase "4.1.1" - lodash.kebabcase "4.0.1" - lodash.snakecase "4.0.1" + lodash.camelcase "4.3.0" + lodash.kebabcase "4.1.1" + lodash.snakecase "4.1.1" + lodash.upperfirst "4.3.1" -eslint-plugin-html@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-2.0.1.tgz#3a829510e82522f1e2e44d55d7661a176121fce1" +eslint-plugin-html@4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-4.0.3.tgz#97d52dcf9e22724505d02719fbd02754013c8a17" dependencies: htmlparser2 "^3.8.2" -eslint-plugin-import@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz#72ba306fad305d67c4816348a4699a4229ac8b4e" +eslint-plugin-import@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.12.0.tgz#dad31781292d6664b25317fd049d2e2b2f02205d" dependencies: - builtin-modules "^1.1.1" contains-path "^0.1.0" - debug "^2.2.0" + debug "^2.6.8" doctrine "1.5.0" - eslint-import-resolver-node "^0.2.0" - eslint-module-utils "^2.0.0" + eslint-import-resolver-node "^0.3.1" + eslint-module-utils "^2.2.0" has "^1.0.1" - lodash.cond "^4.3.0" + lodash "^4.17.4" minimatch "^3.0.3" - pkg-up "^1.0.0" + read-pkg-up "^2.0.0" + resolve "^1.6.0" eslint-plugin-jasmine@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/eslint-plugin-jasmine/-/eslint-plugin-jasmine-2.2.0.tgz#7135879383c39a667c721d302b9f20f0389543de" -eslint-plugin-promise@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca" +eslint-plugin-promise@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621" eslint-plugin-vue@^4.0.1: version "4.0.1" @@ -3022,7 +2976,11 @@ eslint-plugin-vue@^4.0.1: require-all "^2.2.0" vue-eslint-parser "^2.0.1" -eslint-scope@^3.7.1: +eslint-restricted-globals@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz#35f0d5cbc64c2e3ed62e93b4b1a7af05ba7ed4d7" + +eslint-scope@^3.7.1, eslint-scope@~3.7.1: version "3.7.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" dependencies: @@ -3033,51 +2991,53 @@ eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" -eslint@^3.18.0: - version "3.19.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" +eslint@~4.12.1: + version "4.12.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.12.1.tgz#5ec1973822b4a066b353770c3c6d69a2a188e880" dependencies: - babel-code-frame "^6.16.0" - chalk "^1.1.3" - concat-stream "^1.5.2" - debug "^2.1.1" - doctrine "^2.0.0" - escope "^3.6.0" - espree "^3.4.0" + ajv "^5.3.0" + babel-code-frame "^6.22.0" + chalk "^2.1.0" + concat-stream "^1.6.0" + cross-spawn "^5.1.0" + debug "^3.0.1" + doctrine "^2.0.2" + eslint-scope "^3.7.1" + espree "^3.5.2" esquery "^1.0.0" estraverse "^4.2.0" esutils "^2.0.2" file-entry-cache "^2.0.0" - glob "^7.0.3" - globals "^9.14.0" - ignore "^3.2.0" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.0.1" + ignore "^3.3.3" imurmurhash "^0.1.4" - inquirer "^0.12.0" - is-my-json-valid "^2.10.0" + inquirer "^3.0.6" is-resolvable "^1.0.0" - js-yaml "^3.5.1" - json-stable-stringify "^1.0.0" + js-yaml "^3.9.1" + json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" - lodash "^4.0.0" - mkdirp "^0.5.0" + lodash "^4.17.4" + minimatch "^3.0.2" + mkdirp "^0.5.1" natural-compare "^1.4.0" optionator "^0.8.2" - path-is-inside "^1.0.1" - pluralize "^1.2.1" - progress "^1.1.8" - require-uncached "^1.0.2" - shelljs "^0.7.5" - strip-bom "^3.0.0" + path-is-inside "^1.0.2" + pluralize "^7.0.0" + progress "^2.0.0" + require-uncached "^1.0.3" + semver "^5.3.0" + strip-ansi "^4.0.0" strip-json-comments "~2.0.1" - table "^3.7.8" + table "^4.0.1" text-table "~0.2.0" - user-home "^2.0.0" -espree@^3.4.0, espree@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.2.tgz#756ada8b979e9dcfcdb30aad8d1a9304a905e1ca" +espree@^3.5.2: + version "3.5.4" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" dependencies: - acorn "^5.2.1" + acorn "^5.5.0" acorn-jsx "^3.0.0" esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1: @@ -3129,13 +3089,6 @@ eve-raphael@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/eve-raphael/-/eve-raphael-0.5.0.tgz#17c754b792beef3fa6684d79cf5a47c63c4cda30" -event-emitter@~0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - dependencies: - d "1" - es5-ext "~0.10.14" - event-stream@~3.3.0: version "3.3.4" resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" @@ -3289,7 +3242,7 @@ extend@3, extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" -external-editor@^2.1.0: +external-editor@^2.0.4, external-editor@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" dependencies: @@ -3362,7 +3315,7 @@ faye-websocket@~0.11.0: dependencies: websocket-driver ">=0.5.1" -figures@^1.3.5, figures@^1.7.0: +figures@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" dependencies: @@ -3447,9 +3400,9 @@ find-cache-dir@^1.0.0: make-dir "^1.0.0" pkg-dir "^2.0.0" -find-root@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/find-root/-/find-root-0.1.2.tgz#98d2267cff1916ccaf2743b3a0eea81d79d7dcd1" +find-root@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" find-up@^1.0.0: version "1.1.2" @@ -3627,6 +3580,10 @@ function-bind@^1.0.2, function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + fuzzaldrin-plus@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/fuzzaldrin-plus/-/fuzzaldrin-plus-0.5.0.tgz#ef5f26f0c2fc7e9e9a16ea149a802d6cb4804b1e" @@ -3776,11 +3733,11 @@ global-prefix@^1.0.1: is-windows "^1.0.1" which "^1.2.14" -globals@^10.0.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-10.4.0.tgz#5c477388b128a9e4c5c5d01c7a2aca68c68b2da7" +globals@^11.0.1, globals@^11.1.0: + version "11.5.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.5.0.tgz#6bc840de6771173b191f13d3a9c94d441ee92642" -globals@^9.14.0, globals@^9.18.0: +globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" @@ -4216,9 +4173,9 @@ httpreq@>=0.4.22: version "0.4.24" resolved "https://registry.yarnpkg.com/httpreq/-/httpreq-0.4.24.tgz#4335ffd82cd969668a39465c929ac61d6393627f" -https-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" https-proxy-agent@1: version "1.0.0" @@ -4258,9 +4215,9 @@ ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" -ignore@^3.2.0, ignore@^3.3.5, ignore@^3.3.7: - version "3.3.7" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" +ignore@^3.3.3, ignore@^3.3.5, ignore@^3.3.7: + version "3.3.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.8.tgz#3f8e9c35d38708a3a7e0e9abb6c73e7ee7707b2b" immediate@~3.0.5: version "3.0.6" @@ -4333,22 +4290,23 @@ ini@^1.3.4, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" -inquirer@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" +inquirer@^3.0.6: + version "3.3.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" dependencies: - ansi-escapes "^1.1.0" - ansi-regex "^2.0.0" - chalk "^1.0.0" - cli-cursor "^1.0.1" + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" cli-width "^2.0.0" - figures "^1.3.5" + external-editor "^2.0.4" + figures "^2.0.0" lodash "^4.3.0" - readline2 "^1.0.1" - run-async "^0.1.0" - rx-lite "^3.1.2" - string-width "^1.0.1" - strip-ansi "^3.0.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.1.0" + strip-ansi "^4.0.0" through "^2.3.6" inquirer@^5.1.0, inquirer@^5.2.0: @@ -4412,13 +4370,6 @@ is-absolute-url@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" -is-absolute@^0.2.3: - version "0.2.6" - resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-0.2.6.tgz#20de69f3db942ef2d87b9c2da36f172235b1b5eb" - dependencies: - is-relative "^0.2.1" - is-windows "^0.2.0" - is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -4560,7 +4511,7 @@ is-my-ip-valid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" -is-my-json-valid@^2.10.0, is-my-json-valid@^2.12.4: +is-my-json-valid@^2.12.4: version "2.17.2" resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz#6b2103a288e94ef3de5cf15d29dd85fc4b78d65c" dependencies: @@ -4666,12 +4617,6 @@ is-regex@^1.0.4: dependencies: has "^1.0.1" -is-relative@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-0.2.1.tgz#d27f4c7d516d175fb610db84bbeef23c3bc97aa5" - dependencies: - is-unc-path "^0.1.1" - is-resolvable@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" @@ -4706,20 +4651,10 @@ is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" -is-unc-path@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-0.1.2.tgz#6ab053a72573c10250ff416a3814c35178af39b9" - dependencies: - unc-path-regex "^0.1.0" - is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" -is-windows@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" - is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -4901,9 +4836,9 @@ js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" -js-yaml@3.x, js-yaml@^3.5.1, js-yaml@^3.7.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0" +js-yaml@3.x, js-yaml@^3.7.0, js-yaml@^3.9.1: + version "3.11.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -4963,6 +4898,10 @@ jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" +jsesc@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" + jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" @@ -4983,7 +4922,11 @@ json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" -json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + +json-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" dependencies: @@ -5252,6 +5195,15 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" @@ -5280,65 +5232,21 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" -lodash._baseget@^3.0.0: - version "3.7.2" - resolved "https://registry.yarnpkg.com/lodash._baseget/-/lodash._baseget-3.7.2.tgz#1b6ae1d5facf3c25532350a13c1197cb8bb674f4" - -lodash._topath@^3.0.0: - version "3.8.1" - resolved "https://registry.yarnpkg.com/lodash._topath/-/lodash._topath-3.8.1.tgz#3ec5e2606014f4cb97f755fe6914edd8bfc00eac" - dependencies: - lodash.isarray "^3.0.0" - -lodash.camelcase@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.1.1.tgz#065b3ff08f0b7662f389934c46a5504c90e0b2d8" - dependencies: - lodash.capitalize "^4.0.0" - lodash.deburr "^4.0.0" - lodash.words "^4.0.0" - -lodash.camelcase@^4.3.0: +lodash.camelcase@4.3.0, lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" -lodash.capitalize@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz#f826c9b4e2a8511d84e3aca29db05e1a4f3b72a9" - lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" -lodash.cond@^4.3.0: - version "4.5.2" - resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" - -lodash.deburr@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/lodash.deburr/-/lodash.deburr-4.1.0.tgz#ddb1bbb3ef07458c0177ba07de14422cb033ff9b" - lodash.escaperegexp@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" -lodash.get@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-3.7.0.tgz#3ce68ae2c91683b281cc5394128303cbf75e691f" - dependencies: - lodash._baseget "^3.0.0" - lodash._topath "^3.0.0" - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - -lodash.kebabcase@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.0.1.tgz#5e63bc9aa2a5562ff3b97ca7af2f803de1bcb90e" - dependencies: - lodash.deburr "^4.0.0" - lodash.words "^4.0.0" +lodash.kebabcase@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" lodash.memoize@^4.1.2: version "4.1.2" @@ -5348,20 +5256,17 @@ lodash.mergewith@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" -lodash.snakecase@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.0.1.tgz#bd012e5d2f93f7b58b9303e9a7fbfd5db13d6281" - dependencies: - lodash.deburr "^4.0.0" - lodash.words "^4.0.0" +lodash.snakecase@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash.words@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.words/-/lodash.words-4.2.0.tgz#5ecfeaf8ecf8acaa8e0c8386295f1993c9cf4036" +lodash.upperfirst@4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" lodash@4.17.4: version "4.17.4" @@ -5789,10 +5694,6 @@ multimatch@^2.0.0: arrify "^1.0.0" minimatch "^3.0.0" -mute-stream@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" - mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -5846,57 +5747,29 @@ node-forge@0.6.33: version "0.6.33" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.6.33.tgz#463811879f573d45155ad6a9f43dc296e8e85ebc" -node-libs-browser@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-1.1.1.tgz#2a38243abedd7dffcd07a97c9aca5668975a6fea" - dependencies: - assert "^1.1.1" - browserify-zlib "^0.1.4" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^1.0.0" - https-browserify "0.0.1" - os-browserify "^0.2.0" - path-browserify "0.0.0" - process "^0.11.0" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.0.5" - stream-browserify "^2.0.1" - stream-http "^2.3.1" - string_decoder "^0.10.25" - timers-browserify "^1.4.2" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.10.3" - vm-browserify "0.0.4" - -node-libs-browser@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.0.0.tgz#a3a59ec97024985b46e958379646f96c4b616646" +"node-libs-browser@^1.0.0 || ^2.0.0", node-libs-browser@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" dependencies: assert "^1.1.1" - browserify-zlib "^0.1.4" + browserify-zlib "^0.2.0" buffer "^4.3.0" console-browserify "^1.1.0" constants-browserify "^1.0.0" crypto-browserify "^3.11.0" domain-browser "^1.1.1" events "^1.0.0" - https-browserify "0.0.1" - os-browserify "^0.2.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" path-browserify "0.0.0" - process "^0.11.0" + process "^0.11.10" punycode "^1.2.4" querystring-es3 "^0.2.0" - readable-stream "^2.0.5" + readable-stream "^2.3.3" stream-browserify "^2.0.1" - stream-http "^2.3.1" - string_decoder "^0.10.25" - timers-browserify "^2.0.2" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" tty-browserify "0.0.0" url "^0.11.0" util "^0.10.3" @@ -6191,9 +6064,9 @@ original@>=0.0.5: dependencies: url-parse "1.0.x" -os-browserify@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.2.1.tgz#63fc4ccee5d2d7763d26bbf8601078e6c2e0044f" +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" os-homedir@^1.0.0: version "1.0.2" @@ -6313,11 +6186,7 @@ package-json@^4.0.0: registry-url "^3.0.3" semver "^5.1.0" -pako@~0.2.0: - version "0.2.9" - resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" - -pako@~1.0.2: +pako@~1.0.2, pako@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" @@ -6407,7 +6276,7 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" -path-is-inside@^1.0.1: +path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" @@ -6437,6 +6306,12 @@ path-type@^1.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -6503,15 +6378,9 @@ pkg-dir@^2.0.0: dependencies: find-up "^2.1.0" -pkg-up@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-1.0.0.tgz#3e08fb461525c4421624a33b9f7e6d0af5b05a26" - dependencies: - find-up "^1.0.0" - -pluralize@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" +pluralize@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" popper.js@^1.14.3: version "1.14.3" @@ -6829,13 +6698,13 @@ process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" -process@^0.11.0, process@~0.11.0: +process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" -progress@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" +progress@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" promise-inflight@^1.0.1: version "1.0.1" @@ -7043,6 +6912,13 @@ read-pkg-up@^1.0.1: find-up "^1.0.0" read-pkg "^1.0.0" +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + read-pkg-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" @@ -7058,6 +6934,14 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -7066,7 +6950,7 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3: +"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3: version "2.3.4" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.4.tgz#c946c3f47fa7d8eabc0b6150f4a12f69a4574071" dependencies: @@ -7087,6 +6971,18 @@ readable-stream@1.1.x, "readable-stream@1.x >=1.1.9": isarray "0.0.1" string_decoder "~0.10.x" +readable-stream@^2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + readable-stream@~2.0.5, readable-stream@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" @@ -7107,14 +7003,6 @@ readdirp@^2.0.0: readable-stream "^2.0.2" set-immediate-shim "^1.0.1" -readline2@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - mute-stream "0.0.5" - recast@^0.12.5: version "0.12.9" resolved "https://registry.yarnpkg.com/recast/-/recast-0.12.9.tgz#e8e52bdb9691af462ccbd7c15d5a5113647a15f1" @@ -7376,7 +7264,7 @@ require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" -require-uncached@^1.0.2: +require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" dependencies: @@ -7416,9 +7304,9 @@ resolve@1.1.x: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@^1.1.6, resolve@^1.2.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" +resolve@^1.1.6, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0: + version "1.7.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" dependencies: path-parse "^1.0.5" @@ -7469,12 +7357,6 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^2.0.0" inherits "^2.0.1" -run-async@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" - dependencies: - once "^1.3.0" - run-async@^2.0.0, run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" @@ -7487,9 +7369,15 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rx-lite@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" rxjs@^5.4.2, rxjs@^5.5.2: version "5.5.10" @@ -7677,14 +7565,6 @@ shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" -shelljs@^0.7.5: - version "0.7.8" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - shelljs@^0.8.0: version "0.8.1" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.1.tgz#729e038c413a2254c4078b95ed46e0397154a9f1" @@ -7711,6 +7591,12 @@ slice-ansi@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" +slice-ansi@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + dependencies: + is-fullwidth-code-point "^2.0.0" + slide@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -7892,10 +7778,14 @@ source-map@^0.4.4: dependencies: amdefine ">=0.0.4" -source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.6: +source-map@^0.5.0, source-map@^0.5.7, source-map@~0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" +source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -8029,13 +7919,13 @@ stream-each@^1.1.0: end-of-stream "^1.1.0" stream-shift "^1.0.0" -stream-http@^2.3.1: - version "2.8.0" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.0.tgz#fd86546dac9b1c91aff8fc5d287b98fafb41bc10" +stream-http@^2.7.2: + version "2.8.2" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.2.tgz#4126e8c6b107004465918aa2fc35549e77402c87" dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.1" - readable-stream "^2.3.3" + readable-stream "^2.3.6" to-arraybuffer "^1.0.0" xtend "^4.0.0" @@ -8081,7 +7971,13 @@ string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string_decoder@^0.10.25, string_decoder@~0.10.x: +string_decoder@^1.0.0, string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + +string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" @@ -8189,16 +8085,16 @@ symbol-observable@^0.2.2: version "0.2.4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-0.2.4.tgz#95a83db26186d6af7e7a18dbd9760a2f86d08f40" -table@^3.7.8: - version "3.8.3" - resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" +table@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" dependencies: - ajv "^4.7.0" - ajv-keywords "^1.0.0" - chalk "^1.1.1" - lodash "^4.0.0" - slice-ansi "0.0.4" - string-width "^2.0.0" + ajv "^5.2.3" + ajv-keywords "^2.1.0" + chalk "^2.1.0" + lodash "^4.17.4" + slice-ansi "1.0.0" + string-width "^2.1.1" tapable@^0.1.8: version "0.1.10" @@ -8301,15 +8197,9 @@ timed-out@^4.0.0, timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" -timers-browserify@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d" - dependencies: - process "~0.11.0" - -timers-browserify@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.4.tgz#96ca53f4b794a5e7c0e1bd7cc88a372298fa01e6" +timers-browserify@^2.0.4: + version "2.0.10" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" dependencies: setimmediate "^1.0.4" @@ -8477,10 +8367,6 @@ ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" -unc-path-regex@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" - undefsafe@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.2.tgz#225f6b9e0337663e0d8e7cfd686fc2836ccace76" @@ -8642,12 +8528,6 @@ use@^2.0.0: isobject "^3.0.0" lazy-cache "^2.0.2" -user-home@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" - dependencies: - os-homedir "^1.0.0" - useragent@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.2.1.tgz#cf593ef4f2d175875e8bb658ea92e18a4fd06d8e" @@ -8753,8 +8633,8 @@ void-elements@^2.0.0: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" vue-eslint-parser@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-2.0.1.tgz#30135771c4fad00fdbac4542a2d59f3b1d776834" + version "2.0.3" + resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz#c268c96c6d94cfe3d938a5f7593959b0ca3360d1" dependencies: debug "^3.1.0" eslint-scope "^3.7.1" -- cgit v1.2.1 From a626675a3738283c2c399cd93b6d4d10a821be6d Mon Sep 17 00:00:00 2001 From: Lukas Eipert Date: Mon, 28 May 2018 10:56:52 +0200 Subject: disable `function-paren-newline` as it conflicts with prettier --- .eslintrc.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc.yml b/.eslintrc.yml index ceacf23f19c..7950d297416 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -51,3 +51,4 @@ rules: space-before-function-paren: 0 curly: 0 arrow-parens: 0 + function-paren-newline: 0 -- cgit v1.2.1 From 76082ce9aa2578d755bfc84c3f4e03f914f68d02 Mon Sep 17 00:00:00 2001 From: Lukas Eipert Date: Mon, 28 May 2018 11:21:43 +0200 Subject: disable rules that might be conflicting with prettier --- .eslintrc.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index 7950d297416..cef538a249d 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -38,7 +38,7 @@ rules: - allow: - __ - _links - no-mixed-operators: 0 + no-mixed-operators: off vue/html-self-closing: - error - html: @@ -48,7 +48,9 @@ rules: svg: always math: always ## Conflicting rules with prettier: - space-before-function-paren: 0 - curly: 0 - arrow-parens: 0 - function-paren-newline: 0 + space-before-function-paren: off + curly: off + arrow-parens: off + function-paren-newline: off + object-curly-newline: off + padded-blocks: off -- cgit v1.2.1 From ee9974b6d1daa03888199caf06e9e4aa8ef87b4b Mon Sep 17 00:00:00 2001 From: Lukas Eipert Date: Mon, 28 May 2018 11:22:54 +0200 Subject: disable prefer-destructuring for now --- .eslintrc.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.eslintrc.yml b/.eslintrc.yml index cef538a249d..ef8ae69cd0a 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -54,3 +54,6 @@ rules: function-paren-newline: off object-curly-newline: off padded-blocks: off + # Disabled for now, to make the eslint 3 -> eslint 4 update smoother + ## Destructuring: https://eslint.org/docs/rules/prefer-destructuring + prefer-destructuring: off -- cgit v1.2.1 From 0692be4c3b235e9affa09e03965431f92f3f62f6 Mon Sep 17 00:00:00 2001 From: Lukas Eipert Date: Mon, 28 May 2018 11:23:16 +0200 Subject: disable no-restricted-globals --- .eslintrc.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.eslintrc.yml b/.eslintrc.yml index ef8ae69cd0a..486e9b0195e 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -57,3 +57,5 @@ rules: # Disabled for now, to make the eslint 3 -> eslint 4 update smoother ## Destructuring: https://eslint.org/docs/rules/prefer-destructuring prefer-destructuring: off + ## no-restricted-globals: https://eslint.org/docs/3.0.0/rules/no-restricted-globals + no-restricted-globals: off -- cgit v1.2.1 From ef849c6ce7165dd7a9ac10b72eebbd273b8f92e3 Mon Sep 17 00:00:00 2001 From: Lukas Eipert Date: Mon, 28 May 2018 11:24:00 +0200 Subject: use the old indent-rule for now --- .eslintrc.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.eslintrc.yml b/.eslintrc.yml index 486e9b0195e..794afe0cf32 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -55,6 +55,20 @@ rules: object-curly-newline: off padded-blocks: off # Disabled for now, to make the eslint 3 -> eslint 4 update smoother + ## Indent rule. We are using the old for now: https://eslint.org/docs/user-guide/migrating-to-4.0.0#indent-rewrite + indent: off + indent-legacy: + - error + - 2 + - SwitchCase: 1 + VariableDeclarator: 1 + outerIIFEBody: 1 + FunctionDeclaration: + parameters: 1 + body: 1 + FunctionExpression: + parameters: 1 + body: 1 ## Destructuring: https://eslint.org/docs/rules/prefer-destructuring prefer-destructuring: off ## no-restricted-globals: https://eslint.org/docs/3.0.0/rules/no-restricted-globals -- cgit v1.2.1 From 99c4e46d1df36ed7830dfaef2e146177752f244f Mon Sep 17 00:00:00 2001 From: Lukas Eipert Date: Mon, 28 May 2018 11:47:59 +0200 Subject: fix `no-unused-vars` --- .../javascripts/boards/components/modal/list.js | 9 +- .../boards/components/project_select.vue | 112 ++++++++++----------- app/assets/javascripts/ide/lib/common/model.js | 1 - app/assets/javascripts/ide/stores/actions/file.js | 6 +- .../ide/stores/actions/merge_request.js | 6 +- .../javascripts/ide/stores/actions/project.js | 14 +-- app/assets/javascripts/ide/stores/actions/tree.js | 6 +- .../ide/stores/modules/commit/actions.js | 11 +- .../javascripts/jobs/job_details_mediator.js | 5 +- app/assets/javascripts/notes/stores/actions.js | 69 ++++--------- app/assets/javascripts/registry/stores/actions.js | 22 ++-- spec/javascripts/boards/board_blank_state_spec.js | 1 - spec/javascripts/boards/board_card_spec.js | 1 - spec/javascripts/boards/board_list_spec.js | 1 - spec/javascripts/boards/board_new_issue_spec.js | 1 - spec/javascripts/boards/boards_store_spec.js | 1 - spec/javascripts/boards/issue_spec.js | 1 - spec/javascripts/boards/list_spec.js | 1 - 18 files changed, 109 insertions(+), 159 deletions(-) diff --git a/app/assets/javascripts/boards/components/modal/list.js b/app/assets/javascripts/boards/components/modal/list.js index 6c662432037..f86896d2178 100644 --- a/app/assets/javascripts/boards/components/modal/list.js +++ b/app/assets/javascripts/boards/components/modal/list.js @@ -1,5 +1,3 @@ -/* global ListIssue */ - import Vue from 'vue'; import bp from '../../../breakpoints'; import ModalStore from '../../stores/modal_store'; @@ -56,8 +54,11 @@ gl.issueBoards.ModalList = Vue.extend({ scrollHandler() { const currentPage = Math.floor(this.issues.length / this.perPage); - if ((this.scrollTop() > this.scrollHeight() - 100) && !this.loadingNewPage - && currentPage === this.page) { + if ( + this.scrollTop() > this.scrollHeight() - 100 && + !this.loadingNewPage && + currentPage === this.page + ) { this.loadingNewPage = true; this.page += 1; } diff --git a/app/assets/javascripts/boards/components/project_select.vue b/app/assets/javascripts/boards/components/project_select.vue index 371774098b9..eb335f352d3 100644 --- a/app/assets/javascripts/boards/components/project_select.vue +++ b/app/assets/javascripts/boards/components/project_select.vue @@ -1,71 +1,69 @@