diff --git a/.gitignore b/.gitignore index 65befc2096..b8cbfe9966 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,7 @@ eslint-report.html /public/uploads.* /public/uploads/ /shared/artifacts/ +/spec/examples.txt /rails_best_practices_output.html /tags /vendor/bundle/* @@ -82,3 +83,4 @@ jsdoc/ **/tmp/rubocop_cache/** .overcommit.yml .projections.json +/qa/.rakeTasks diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 630c82bcc5..36108d04e9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,7 @@ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.22-chrome-73.0-node-12.x-yarn-1.16-postgresql-9.6-graphicsmagick-1.3.33" stages: + - sync - prepare - quick-test - test @@ -8,7 +9,6 @@ stages: - review - qa - post-test - - notification - pages variables: @@ -33,7 +33,6 @@ include: - local: .gitlab/ci/frontend.gitlab-ci.yml - local: .gitlab/ci/global.gitlab-ci.yml - local: .gitlab/ci/memory.gitlab-ci.yml - - local: .gitlab/ci/notifications.gitlab-ci.yml - local: .gitlab/ci/pages.gitlab-ci.yml - local: .gitlab/ci/qa.gitlab-ci.yml - local: .gitlab/ci/reports.gitlab-ci.yml @@ -42,3 +41,4 @@ include: - local: .gitlab/ci/setup.gitlab-ci.yml - local: .gitlab/ci/test-metadata.gitlab-ci.yml - local: .gitlab/ci/yaml.gitlab-ci.yml + - local: .gitlab/ci/releases.gitlab-ci.yml diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index a02740373d..c828332653 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -3,11 +3,12 @@ *.rake @gitlab-org/maintainers/rails-backend # Technical writing team are the default reviewers for everything in `doc/` -/doc/ @axil @marcia @eread @mikelewis +/doc/ @gl-docsteam # Frontend maintainers should see everything in `app/assets/` -app/assets/ @ClemMakesApps @fatihacet @filipa @mikegreiling @timzallmann @kushalpandya @pslaughter @wortschi @ntepluhina -*.scss @annabeldunstone @ClemMakesApps @fatihacet @filipa @mikegreiling @timzallmann @kushalpandya @pslaughter @wortschi @ntepluhina +app/assets/ @gitlab-org/maintainers/frontend +*.scss @annabeldunstone @gitlab-org/maintainers/frontend +/scripts/frontend/ @gitlab-org/maintainers/frontend # Database maintainers should review changes in `db/` db/ @gitlab-org/maintainers/database @@ -32,4 +33,5 @@ lib/gitlab/github_import/ @gitlab-org/maintainers/database /.gitlab/ci/ @gl-quality/eng-prod Dangerfile @gl-quality/eng-prod /danger/ @gl-quality/eng-prod +/lib/gitlab/danger/ @gl-quality/eng-prod /scripts/ @gl-quality/eng-prod diff --git a/.gitlab/ci/cng.gitlab-ci.yml b/.gitlab/ci/cng.gitlab-ci.yml index 35859a1ab3..bd11042eb1 100644 --- a/.gitlab/ci/cng.gitlab-ci.yml +++ b/.gitlab/ci/cng.gitlab-ci.yml @@ -1,4 +1,5 @@ cloud-native-image: + extends: .only:variables-canonical-dot-com image: ruby:2.6-alpine dependencies: [] stage: post-test @@ -12,5 +13,3 @@ cloud-native-image: only: refs: - tags - variables: - - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml index 14eeebb9db..07375fca61 100644 --- a/.gitlab/ci/docs.gitlab-ci.yml +++ b/.gitlab/ci/docs.gitlab-ci.yml @@ -2,12 +2,11 @@ extends: - .default-tags - .default-retry - - .only-docs-changes + - .only:variables-canonical-dot-com + - .only:changes-docs only: refs: - merge_requests - variables: - - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" image: ruby:2.6-alpine stage: review dependencies: [] @@ -50,7 +49,7 @@ docs lint: - .default-tags - .default-retry - .default-only - - .only-docs-changes + - .only:changes-docs image: "registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-docs-lint" stage: test dependencies: [] @@ -68,7 +67,7 @@ docs lint: # Check the internal anchor links - bundle exec nanoc check internal_anchors -graphql-docs-verify: +graphql-reference-verify: extends: - .only-ee - .default-tags @@ -76,10 +75,10 @@ graphql-docs-verify: - .default-cache - .default-only - .default-before_script - - .only-graphql-changes - variables: - SETUP_DB: "false" + - .only:changes-code-backstage-qa + - .use-pg9 stage: test needs: ["setup-test-env"] script: - bundle exec rake gitlab:graphql:check_docs + - bundle exec rake gitlab:graphql:check_schema diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml index 2f457bc0ee..0b72461a9f 100644 --- a/.gitlab/ci/frontend.gitlab-ci.yml +++ b/.gitlab/ci/frontend.gitlab-ci.yml @@ -12,7 +12,7 @@ - .default-only - .default-before_script - .assets-compile-cache - - .only-code-qa-changes + - .only:changes-code-backstage-qa image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.6.3-git-2.22-chrome-73.0-node-12.x-yarn-1.16-graphicsmagick-1.3.33-docker-18.06.1 stage: test dependencies: ["setup-test-env"] @@ -73,7 +73,7 @@ gitlab:assets:compile pull-cache: - .default-only - .default-before_script - .assets-compile-cache - - .only-code-qa-changes + - .only:changes-code-backstage-qa - .use-pg9 stage: prepare script: @@ -128,7 +128,7 @@ compile-assets pull-cache foss: - .default-cache - .default-only - .default-before_script - - .only-code-changes + - .only:changes-code-backstage - .use-pg9 stage: test needs: ["setup-test-env", "compile-assets pull-cache"] @@ -205,7 +205,7 @@ jest-foss: - .default-retry - .default-cache - .default-only - - .only-code-changes + - .only:changes-code-backstage stage: test dependencies: [] cache: @@ -238,7 +238,7 @@ webpack-dev-server: - .default-retry - .default-cache - .default-only - - .only-code-changes + - .only:changes-code-backstage stage: test needs: ["setup-test-env", "compile-assets pull-cache"] dependencies: ["setup-test-env", "compile-assets pull-cache"] diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml index fc9b00b5d3..d746d8fe03 100644 --- a/.gitlab/ci/global.gitlab-ci.yml +++ b/.gitlab/ci/global.gitlab-ci.yml @@ -40,87 +40,160 @@ - merge_requests - tags -.only-code-changes: - only: - changes: - - ".gitlab/ci/**/*" - - ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}" - - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml" - - ".csscomb.json" - - "Dangerfile" - - "Dockerfile.assets" - - "*_VERSION" - - "Gemfile{,.lock}" - - "Rakefile" - - "{babel.config,jest.config}.js" - - "config.ru" - - "{package.json,yarn.lock}" - - "{app,bin,config,danger,db,ee,fixtures,haml_lint,lib,locale,public,rubocop,scripts,spec,symbol,vendor}/**/*" - - "doc/README.md" # Some RSpec test rely on this file - -.only-qa-changes: - only: - changes: - - ".dockerignore" - - "qa/**/*" - -.only-docs-changes: - only: - changes: - - ".gitlab/route-map.yml" - - "doc/**/*" - - ".markdownlint.json" - -.only-graphql-changes: - only: - changes: - - "{,ee/}app/graphql/**/*" - - "{,ee/}lib/gitlab/graphql/**/*" - -.only-code-qa-changes: - only: - changes: - - ".gitlab/ci/**/*" - - ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}" - - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml" - - ".csscomb.json" - - "Dangerfile" - - "Dockerfile.assets" - - "*_VERSION" - - "Gemfile{,.lock}" - - "Rakefile" - - "{babel.config,jest.config}.js" - - "config.ru" - - "{package.json,yarn.lock}" - - "{app,bin,config,danger,db,ee,fixtures,haml_lint,lib,locale,public,rubocop,scripts,spec,symbol,vendor}/**/*" - - "doc/README.md" # Some RSpec test rely on this file - - ".dockerignore" - - "qa/**/*" - -.only-review: +.only:variables-canonical-dot-com: only: variables: - - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" - kubernetes: active - except: - refs: - - master - - /^\d+-\d+-auto-deploy-\d+$/ - - /^[\d-]+-stable(-ee)?$/ + - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/)/ # Matches the gitlab-org group or its subgroups -.only-review-schedules: +.only:variables_refs-canonical-dot-com-schedules: + extends: .only:variables-canonical-dot-com only: refs: - schedules - variables: - - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" + +.except:refs-deploy: + except: + refs: + - /^\d+-\d+-auto-deploy-\d+$/ + +.except:refs-master-tags-stable-deploy: + except: + refs: + - master + - tags + - /^[\d-]+-stable(-ee)?$/ + - /^\d+-\d+-auto-deploy-\d+$/ + +.only:kubernetes: + only: kubernetes: active -.only-canonical-schedules: +.only-review: + extends: + - .only:variables-canonical-dot-com + - .only:kubernetes + - .except:refs-master-tags-stable-deploy + +.only-review-schedules: + extends: + - .only:variables_refs-canonical-dot-com-schedules + - .only:kubernetes + - .except:refs-deploy + +.code-patterns: &code-patterns + - ".gitlab/ci/**/*" + - ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}" + - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml" + - ".csscomb.json" + - "Dockerfile.assets" + - "*_VERSION" + - "Gemfile{,.lock}" + - "Rakefile" + - "{babel.config,jest.config}.js" + - "config.ru" + - "{package.json,yarn.lock}" + - "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*" + - "doc/api/graphql/**/*" + +.backstage-patterns: &backstage-patterns + - "Dangerfile" + - "danger/**/*" + - "{,ee/}fixtures/**/*" + - "{,ee/}rubocop/**/*" + - "{,ee/}spec/**/*" + - "doc/README.md" # Some RSpec test rely on this file + +.qa-patterns: &qa-patterns + - ".dockerignore" + - "qa/**/*" + +.docs-patterns: &docs-patterns + - ".gitlab/route-map.yml" + - "doc/**/*" + - ".markdownlint.json" + +.only:changes-code: only: - refs: - - schedules@gitlab-org/gitlab - - schedules@gitlab-org/gitlab-foss + changes: *code-patterns + +.only:changes-qa: + only: + changes: *qa-patterns + +.only:changes-docs: + only: + changes: *docs-patterns + +.only:changes-code-backstage: + only: + changes: + - ".gitlab/ci/**/*" + - ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}" + - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml" + - ".csscomb.json" + - "Dockerfile.assets" + - "*_VERSION" + - "Gemfile{,.lock}" + - "Rakefile" + - "{babel.config,jest.config}.js" + - "config.ru" + - "{package.json,yarn.lock}" + - "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*" + - "doc/api/graphql/**/*" + # Backstage changes + - "Dangerfile" + - "danger/**/*" + - "{,ee/}fixtures/**/*" + - "{,ee/}rubocop/**/*" + - "{,ee/}spec/**/*" + - "doc/README.md" # Some RSpec test rely on this file + +.only:changes-code-qa: + only: + changes: + - ".gitlab/ci/**/*" + - ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}" + - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml" + - ".csscomb.json" + - "Dockerfile.assets" + - "*_VERSION" + - "Gemfile{,.lock}" + - "Rakefile" + - "{babel.config,jest.config}.js" + - "config.ru" + - "{package.json,yarn.lock}" + - "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*" + - "doc/api/graphql/**/*" + # QA changes + - ".dockerignore" + - "qa/**/*" + +.only:changes-code-backstage-qa: + only: + changes: + - ".gitlab/ci/**/*" + - ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}" + - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml" + - ".csscomb.json" + - "Dockerfile.assets" + - "*_VERSION" + - "Gemfile{,.lock}" + - "Rakefile" + - "{babel.config,jest.config}.js" + - "config.ru" + - "{package.json,yarn.lock}" + - "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*" + - "doc/api/graphql/**/*" + # Backstage changes + - "Dangerfile" + - "danger/**/*" + - "{,ee/}fixtures/**/*" + - "{,ee/}rubocop/**/*" + - "{,ee/}spec/**/*" + - "doc/README.md" # Some RSpec test rely on this file + # QA changes + - ".dockerignore" + - "qa/**/*" .use-pg9: services: diff --git a/.gitlab/ci/memory.gitlab-ci.yml b/.gitlab/ci/memory.gitlab-ci.yml index 93bf87b24b..ba14024df3 100644 --- a/.gitlab/ci/memory.gitlab-ci.yml +++ b/.gitlab/ci/memory.gitlab-ci.yml @@ -5,7 +5,7 @@ - .default-cache - .default-only - .default-before_script - - .only-code-changes + - .only:changes-code memory-static: extends: .only-code-memory-job-base diff --git a/.gitlab/ci/notifications.gitlab-ci.yml b/.gitlab/ci/notifications.gitlab-ci.yml deleted file mode 100644 index 8e00ba022d..0000000000 --- a/.gitlab/ci/notifications.gitlab-ci.yml +++ /dev/null @@ -1,29 +0,0 @@ -.notify: - image: alpine - stage: notification - dependencies: [] - cache: {} - before_script: - - apk update && apk add git curl bash - -schedule:package-and-qa:notify-success: - extends: - - .only-canonical-schedules - - .notify - variables: - COMMIT_NOTES_URL: "https://$CI_SERVER_HOST/$CI_PROJECT_PATH/commit/$CI_COMMIT_SHA#notes-list" - script: - - 'scripts/notify-slack qa-master ":tada: Scheduled QA against master passed! :tada: See $CI_PIPELINE_URL. For downstream pipelines, see $COMMIT_NOTES_URL" ci_passing' - needs: ["schedule:package-and-qa"] - when: on_success - -schedule:package-and-qa:notify-failure: - extends: - - .only-canonical-schedules - - .notify - variables: - COMMIT_NOTES_URL: "https://$CI_SERVER_HOST/$CI_PROJECT_PATH/commit/$CI_COMMIT_SHA#notes-list" - script: - - 'scripts/notify-slack qa-master ":skull_and_crossbones: Scheduled QA against master failed! :skull_and_crossbones: See $CI_PIPELINE_URL. For downstream pipelines, see $COMMIT_NOTES_URL" ci_failing' - needs: ["schedule:package-and-qa"] - when: on_failure diff --git a/.gitlab/ci/pages.gitlab-ci.yml b/.gitlab/ci/pages.gitlab-ci.yml index a30772d566..6a2d3702bd 100644 --- a/.gitlab/ci/pages.gitlab-ci.yml +++ b/.gitlab/ci/pages.gitlab-ci.yml @@ -4,12 +4,11 @@ pages: - .default-retry - .default-cache - .default-only - - .only-code-qa-changes + - .only:variables-canonical-dot-com + - .only:changes-code-backstage-qa only: refs: - master - variables: - - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" stage: pages dependencies: ["coverage", "karma", "gitlab:assets:compile pull-cache"] script: diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml index 1194948a76..3cb5a40a8b 100644 --- a/.gitlab/ci/qa.gitlab-ci.yml +++ b/.gitlab/ci/qa.gitlab-ci.yml @@ -3,7 +3,7 @@ - .default-tags - .default-retry - .default-only - - .only-code-qa-changes + - .only:changes-code-qa stage: test dependencies: [] cache: @@ -31,7 +31,6 @@ qa:selectors-foss: - .only-ee-as-if-foss .package-and-qa-base: - extends: .default-only image: ruby:2.6-alpine stage: qa dependencies: [] @@ -40,35 +39,31 @@ qa:selectors-foss: - source scripts/utils.sh - install_gitlab_gem - ./scripts/trigger-build omnibus - only: - variables: - - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/)/ # Matches the gitlab-org group or its subgroups package-and-qa-manual: extends: - .package-and-qa-base - - .only-code-changes - except: - refs: - - master - - /^\d+-\d+-auto-deploy-\d+$/ + - .default-only + - .only:variables-canonical-dot-com + - .except:refs-deploy + - .only:changes-code when: manual needs: ["build-qa-image", "gitlab:assets:compile pull-cache"] package-and-qa: extends: - .package-and-qa-base - - .only-qa-changes - except: - refs: - - master - - /^\d+-\d+-auto-deploy-\d+$/ + - .default-only + - .only:variables-canonical-dot-com + - .except:refs-master-tags-stable-deploy + - .only:changes-qa needs: ["build-qa-image", "gitlab:assets:compile pull-cache"] allow_failure: true schedule:package-and-qa: extends: - .package-and-qa-base - - .only-code-qa-changes - - .only-canonical-schedules + - .default-only + - .only:variables_refs-canonical-dot-com-schedules needs: ["build-qa-image", "gitlab:assets:compile pull-cache"] + allow_failure: true diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml index bf478b6876..4ac187e167 100644 --- a/.gitlab/ci/rails.gitlab-ci.yml +++ b/.gitlab/ci/rails.gitlab-ci.yml @@ -22,7 +22,7 @@ - .default-cache - .default-only - .default-before_script - - .only-code-changes + - .only:changes-code-backstage .only-code-qa-rails-job-base: extends: @@ -31,7 +31,7 @@ - .default-cache - .default-only - .default-before_script - - .only-code-qa-changes + - .only:changes-code-backstage-qa setup-test-env: extends: @@ -92,6 +92,14 @@ setup-test-env: - .use-pg10 - .only-master +rspec migration pg9: + extends: .rspec-base-pg9 + parallel: 4 + +rspec migration pg9-foss: + extends: .rspec-base-pg9-foss + parallel: 4 + rspec unit pg9: extends: .rspec-base-pg9 parallel: 20 @@ -140,9 +148,13 @@ rspec system pg10: - .only-ee - .use-pg10-ee +rspec-ee migration pg9: + extends: .rspec-ee-base-pg9 + parallel: 2 + rspec-ee unit pg9: extends: .rspec-ee-base-pg9 - parallel: 7 + parallel: 5 rspec-ee integration pg9: extends: .rspec-ee-base-pg9 @@ -152,11 +164,17 @@ rspec-ee system pg9: extends: .rspec-ee-base-pg9 parallel: 5 +rspec-ee migration pg10: + extends: + - .rspec-ee-base-pg10 + - .only-master + parallel: 2 + rspec-ee unit pg10: extends: - .rspec-ee-base-pg10 - .only-master - parallel: 7 + parallel: 5 rspec-ee integration pg10: extends: @@ -239,6 +257,7 @@ static-analysis: dependencies: ["setup-test-env", "compile-assets pull-cache"] variables: SETUP_DB: "false" + parallel: 2 script: - scripts/static-analysis cache: @@ -251,13 +270,8 @@ static-analysis: downtime_check: extends: - .rake-exec - - .only-code-changes - except: - refs: - - master - - tags - variables: - - $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable(-ee)?$/ + - .only:changes-code-backstage + - .except:refs-master-tags-stable-deploy stage: test needs: ["setup-test-env"] dependencies: ["setup-test-env"] diff --git a/.gitlab/ci/releases.gitlab-ci.yml b/.gitlab/ci/releases.gitlab-ci.yml new file mode 100644 index 0000000000..1ddc4e90fc --- /dev/null +++ b/.gitlab/ci/releases.gitlab-ci.yml @@ -0,0 +1,22 @@ +--- + +# Syncs any changes pushed to a stable branch to the corresponding CE stable +# branch. We run this prior to any tests so that random failures don't prevent a +# sync. +sync-stable-branch: + # We don't need/want any global before/after commands, so we overwrite these + # settings. + image: alpine:edge + stage: sync + # This job should only run on EE stable branches on the canonical GitLab.com + # repository. + only: + variables: + - $CI_SERVER_HOST == "gitlab.com" + refs: + - /^[\d-]+-stable-ee$/@gitlab-org/gitlab + before_script: + - apk add --no-cache --update curl bash + after_script: [] + script: + - bash scripts/sync-stable-branch.sh diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml index 16c3f0e4f8..fbb7826b6f 100644 --- a/.gitlab/ci/reports.gitlab-ci.yml +++ b/.gitlab/ci/reports.gitlab-ci.yml @@ -11,7 +11,7 @@ code_quality: extends: - .default-retry - .default-only - - .only-code-changes + - .only:changes-code-backstage stage: test image: docker:stable allow_failure: true @@ -50,7 +50,7 @@ sast: extends: - .default-retry - .default-only - - .only-code-changes + - .only:changes-code-backstage-qa stage: test image: docker:stable variables: @@ -132,7 +132,7 @@ dependency_scanning: extends: - .default-retry - .default-only - - .only-code-changes + - .only:changes-code-backstage-qa stage: test image: docker:stable variables: @@ -195,7 +195,7 @@ dast: extends: - .default-retry - .default-only - - .only-code-qa-changes + - .only:changes-code-qa - .only-review stage: qa needs: ["review-deploy"] diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml index c78c6a8281..4ed9ac03d0 100644 --- a/.gitlab/ci/review.gitlab-ci.yml +++ b/.gitlab/ci/review.gitlab-ci.yml @@ -1,14 +1,8 @@ -.except-deploys: - except: - refs: - - /^\d+-\d+-auto-deploy-\d+$/ - .review-docker: extends: - .default-tags - .default-retry - .default-only - - .except-deploys image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine services: - docker:19.03.0-dind @@ -23,10 +17,9 @@ build-qa-image: extends: - .review-docker - - .only-code-qa-changes - only: - variables: - - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" + - .only:variables-canonical-dot-com + - .except:refs-deploy + - .only:changes-code-qa stage: prepare script: - '[[ ! -d "ee/" ]] || export GITLAB_EDITION="ee"' @@ -35,14 +28,11 @@ build-qa-image: - echo "${CI_JOB_TOKEN}" | docker login --username gitlab-ci-token --password-stdin ${CI_REGISTRY} - time docker push ${QA_IMAGE} -schedule:review-cleanup: +.base-review-cleanup: extends: - .default-tags - .default-retry - .default-only - - .only-code-qa-changes - - .only-review-schedules - - .except-deploys stage: prepare image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base allow_failure: true @@ -55,11 +45,22 @@ schedule:review-cleanup: script: - ruby -rrubygems scripts/review_apps/automated_cleanup.rb +schedule:review-cleanup: + extends: + - .base-review-cleanup + - .only-review-schedules + +manual:review-cleanup: + extends: + - .base-review-cleanup + - .only:changes-code-qa + when: manual + .review-build-cng-base: extends: + - .default-tags + - .default-retry - .default-only - - .only-code-qa-changes - - .except-deploys image: ruby:2.6-alpine stage: review-prepare before_script: @@ -74,6 +75,7 @@ review-build-cng: extends: - .review-build-cng-base - .only-review + - .only:changes-code-qa needs: ["gitlab:assets:compile pull-cache"] schedule:review-build-cng: @@ -82,26 +84,30 @@ schedule:review-build-cng: - .only-review-schedules needs: ["gitlab:assets:compile pull-cache"] -.review-deploy-base: +.review-workflow-base: extends: - .default-tags - .default-retry - .default-only - - .only-code-qa-changes - - .except-deploys - stage: review image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base dependencies: [] - allow_failure: true variables: HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}" DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}" - GITLAB_HELM_CHART_REF: "v2.3.7" + # v2.4.4 + two improvements: + # - Allow to pass an EE license when installing the chart: https://gitlab.com/gitlab-org/charts/gitlab/merge_requests/1008 + # - Allow to customize the livenessProbe for `gitlab-shell`: https://gitlab.com/gitlab-org/charts/gitlab/merge_requests/1021 + GITLAB_HELM_CHART_REF: "6c655ed77e60f1f7f533afb97bef8c9cb7dc61eb" GITLAB_EDITION: "ce" environment: name: review/${CI_COMMIT_REF_NAME} url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN} on_stop: review-stop + +.review-deploy-base: + extends: .review-workflow-base + stage: review + allow_failure: true before_script: - '[[ ! -d "ee/" ]] || export GITLAB_EDITION="ee"' - export GITLAB_SHELL_VERSION=$( Settings > Integrations. !18990 +- Fixed admin geo collapsed sidebar fly out not showing. !19012 +- Serialize short sha as nil if head commit is blank. !19014 +- Add max width on manifest file attachment input. !19028 +- Do not generate To-Dos additional when editing group mentions. !19037 +- Fix previewing quick actions for epics. !19042 +- Fix errors in GraphQL Todos API due to missing TargetTypeEnum values. !19052 +- Hashed Storage Migration: Handle failed attachment migrations with existing target path. !19061 +- Set shorter TTL for all unauthenticated requests. !19064 +- Fix Todo IDs in GraphQL API. !19068 +- Triggers the correct endpoint on licence approval. !19078 +- Fix search button height on 404 page. !19080 +- Fix Kubernetes help text link. !19121 +- Make `jobs/request` to be resillient. !19150 +- Disable pull mirror if repository is in read-only state. !19182 - Only enable protected paths for POST requests. !19184 +- Enforce default, global project and snippet visibilities. !19188 +- Make Bitbucket Cloud superseded pull requests as closed. !19193 +- Fix crash when docker fails deleting tags. !19208 +- Fix environment name in rollback dialog. !19209 +- Fixed a typo in the "Keyboard Shortcuts" pop-up. !19217 (Manuel Stein) +- Fix unable to expand or collapse files in merge request by clicking caret. !19222 (Brian T) +- Allow release block edit button to be visible. !19226 +- Fix double escaping in /tableflip quick action. !19271 (Brian T) +- Add missing bottom padding in CI/CD settings. !19284 (George Tsiolis) +- Prevents console warning on design upload. !19297 +- Resolve: Web IDE does not create POSIX Compliant Files. !19339 +- Use initial commit SHA instead of branch id to request IDE files and contents. !19348 (David Palubin) +- Resolve: Web IDE Throws Error When Viewing Diff for Renamed Files. !19348 +- Fix project service API 500 error. !19367 +- Fix cluster feature highlight popover image. !19372 +- Fix template selector filename bug. !19376 +- Fixes mobile styling issues on security modals. !19391 +- Only move repos for legacy project storage. !19410 +- Show correct total number of commit diff's changes. !19424 +- Increase the timeout for GitLab-managed cert-manager installation to 90 seconds (was 30 seconds). !19447 +- Fix uninitialized constant SystemDashboardService. !19453 +- Properly handle exceptions in StuckCiJobsWorker. !19465 +- Fix user popover not being displayed when the user has a status message. !19519 +- Update omniauth_openid_connect to v0.3.3. !19525 +- Fix project clone dropdown button width. !19551 (George Tsiolis) +- Do not escape HTML tags in Ansi2json as they are escaped in the frontend. !19610 +- [Geo] Fix: undefined Gitlab::BackgroundMigration::PruneOrphanedGeoEvents. !19638 +- Revert btn-xs styling in projects scss. !19640 +- Fix canary badge and favicon inconsistency. !19645 +- Use fingerprint when comparing security reports in MR widget. !19654 +- Update GCP credit URLs. !19683 +- Update squash_commit_sha only on successful merge. !19688 +- Fix import of snippets having `award_emoji` (Project Export/Import). !19690 +- Allow admins to administer personal snippets. !19693 (Oren Kanner) +- Re-add missing file sizes in 2-Up diff file viewer. !19710 +- Fix checking task item when previous tasks contain only spaces. !19724 - Fix Bitbucket Cloud importer pull request state. !19734 +- Fix merge train is not refreshed when the system aborts/drops a merge request. !19763 +- Resolve Hide Delete selected in designs when viewing an old version. !19889 +- Use new trial registration URL in billing. !19978 +- Helm v2.16.1. !19981 +- Ensure milestone titles are never empty. !19985 +- Remove unused image/screenshot. !20030 (Lee Tickett) +- Remove local qualifier from geo sync indicators. !20034 (Lee Tickett) +- Fixed the scale of embedded videos to fit the page. !20056 +- Fix broken monitor cluster health dashboard. !20120 +- Fix expanding collapsed threads when reference link clicked. !20148 +- Fix sub group export to export direct children. !20172 +- Remove update hook from date filter to prevent js from getting stuck. !20215 +- Prevent Dropzone.js initialisation error by checking target element existence. !20256 (Fabio Huser) +- Fix style reset in job log when empty ANSI sequence is encoutered. !20367 +- Add productivity analytics merge date filtering limit. !32052 +- Fix productivity analytics listing with multiple labels. !33182 +- Fix closed board list loading issue. +- Apply correctly the limit of 10 designs per upload. +- Only allow confirmed users to run pipelines. +- Fix scroll to bottom with new job log. +- Fixed protected branches flash styling. + +### Deprecated (2 changes) + +- Ignore deprecated column and remove references to it. !18911 +- Move some project routes under - scope. !19954 + +### Changed (56 changes, 6 of them are from the community) + +- Upgrade design/copy for issue weights locked feature. !17352 +- Reduce new MR page redundancy by moving the source/target branch selector to the top. !17559 +- Replace raven-js with @sentry/browser. !17715 +- Ask if the user is setting up GitLab for a company during signup. !17999 +- When a user views a file's blame or blob and switches to a branch where the current file does not exist, they will now be redirected to the root of the repository. !18169 (Jesse Hall @jessehall3) +- Propagate custom environment variables to SAST analyzers. !18193 +- Fix any approver project rule records. !18265 +- Minor UX improvements to Environments Dashboard page. !18280 +- Reduce the allocated IP for Cluster and Services. !18341 +- Update flash messages color sitewide. !18369 +- Add modsecurity template for ingress-controller. !18485 +- Hide projects without access to admin user when admin mode is disabled. !18530 (Diego Louzán) +- Update Runners Settings Text + Link to Docs. !18534 +- Store Zoom URLs in a table rather than in the issue description. !18620 +- Improve admin dashboard features. !18666 +- Drop `id` column from `ci_build_trace_sections` table. !18741 +- Truncate recommended branch name to a sane length. !18821 +- Add support for YAML anchors in CI scripts. !18849 +- Save dashboard changes by the user into the vuex store. !18862 +- Update expired trial status copy. !18962 +- Can directly add approvers to approval rule. !18965 +- Rename Vulnerabilities API to Vulnerability Findings API. !19029 +- Improve clarity of text for merge train position. !19031 +- Updated Auto-DevOps to kubectl v1.13.12 and helm v2.15.1. !19054 (Leo Antunes) +- Refactor maximum user counts in license. !19071 (briankabiro) +- Change return type of getDateInPast to Date. !19081 +- Show approval required status in license compliance. !19114 +- Handle new Container Scanning report format. !19123 +- Allow container scanning to run offline by specifying the Clair DB image to use. !19161 +- Add maven cli opts flag to maven security analyzer (part of dependency scanning). !19174 +- Added report_type attribute to Vulnerabilities. !19179 +- Migrate enabled flag on grafana_integrations table. !19234 +- Improve handling of gpg-agent processes. !19311 +- Update help text of "Tag name" field on Edit Release page. !19321 +- Add user filtering to abuse reports page. !19365 +- Move add license button to project buttons. !19370 +- Update to Mermaid v8.4.2 to support more graph types. !19444 +- Move release meta-data into footer on Releases page. !19451 +- Expose subscribed field in issue lists queried with GraphQL. !19458 (briankabiro) +- [Geo] Fix: rake gitlab:geo:check on the primary is cluttered. !19460 +- Hide trial banner for namespaces with expired trials. !19510 +- Hide repeated trial offers on self-hosted instances. !19511 +- Add loading icon to error tracking settings page. !19539 +- Upgrade to Gitaly v1.71.0. !19611 +- Make role required when editing profile. !19636 +- Made `name` optional parameter of Release entity. !19705 +- Vulnerabilities history chart - use sparklines. !19745 +- Add event tracking to container registry. !19772 +- Update SaaS trial header to include the tier Gold. !19970 +- Update start a trial option in top right drop down to include Gold. !19971 +- Improve merge request description placeholder. !20032 (Jacopo Beschi @jacopo-beschi) +- Add backtrace to production_json.log. !20122 +- Change the default concurrency factor of merge train to 20. !20201 +- Upgrade to Gitaly v1.72.0. +- Require explicit null parameters to remove pages domain certificate and allow to use Let's Encrypt certificates through API. +- Replace wording trace with log. + +### Performance (13 changes) + +- Record latencies for Sidekiq failures. !18909 +- Fix N+1 for group container repositories view. !18979 +- Do not render links in commit message on blame page. !19128 +- Puma only: database connection pool now always >= number of worker threads. !19286 +- Run check_mergeability only if merge status requires it. !19364 +- Execute limited request for diff commits instead of preloading. !19485 +- Improve performance of admin/abuse_reports page. !19630 +- Remove N+1 DB calls from branches API. !19661 +- Improve performance of linking LFS objects during import. !19709 +- Optimize MergeRequest#mergeable_discussions_state? method. !19988 +- Add index for unauthenticated requests to projects API default endpoint. !19989 +- Add index for authenticated requests to projects API default endpoint. !19993 +- Increase PumaWorkerKiller memory limit in development environment. !20039 + +### Added (83 changes, 8 of them are from the community) + +- Adds Application Settings and ui settings in the integration admin area for Pendo. !15086 +- Add endpoint for a group's vulnerable projects. !15317 +- Added new chart component to display an anomaly boundary. !16530 +- Add links to associated releases on the Milestones page. !16558 +- Merge Details Page and Edit Page for Page Domains. !16687 +- Share groups with groups. !17117 +- Add links to associated release(s) to the milestone detail page. !17278 +- New group path uniqueness check. !17394 +- Unify html email layout for member html emails. !17699 (Diego Louzán) +- The Security Dashboard displays DAST vulnerabilities for all the scanned sites, not just the first. !17779 +- Create table for elastic stack. !18015 +- Allow to define a default CI configuration path for new projects. !18073 (Mathieu Parent) +- Issues queried in GraphQL now sortable by due date. !18094 +- Add cleanup status to clusters. !18144 +- Added Tests tab to pipeline detail that contains a UI for browsing test reports produced by JUnit. !18255 +- Users can verify SAML configuration and view SamlResponse XML. !18362 +- Support Enable/Disable operations in Feature Flag API. !18368 +- Expose arbitrary job artifacts in Merge Request widget. !18385 +- Add project option for deleting source branch. !18408 (Zsolt Kovari) +- Adds ability to set management project for cluster via API. !18429 +- Close issues on Prometheus alert recovery. !18431 +- Add ApplicationSetting for snowplow_iglu_registry_url. !18449 +- Allow Grafana charts to be embedded in Gitlab Flavored Markdown. !18486 +- Mark todo done by GraphQL API. !18581 +- Create a users_security_dashboard_projects table to store the projects a user has added to their personal security dashboard. !18708 +- New API endpoint for creating anonymous merge request discussions from Visual Review Tools. !18710 +- Enable the color chip in AsciiDoc documents. !18723 +- Add prevent_ldap_sign_in option so LDAP can be used exclusively for sync. !18749 +- Show inherited group variables in project view. !18759 +- Add "release" filter to issue search page. !18761 +- Search list of Sentry errors by title in Gitlab. !18772 +- Add migrations and changes for soft-delete for projects. !18791 +- Support for Crossplane as a managed app. !18797 (Mahendra Bagul) +- Bump Auto-Deploy image to v0.3.0. !18809 +- Set X-GitLab-NotificationReason header if notification reason is explicit subscription. !18812 +- Add issues, MRs, participants, and labels tabs in group milestone page. !18818 +- Add ability to reorder projects on operations dashboard. !18855 +- Make `Job`, `Bridge` and `Default` inheritable. !18867 +- Show epic events on group activity page. !18869 +- Detail view of Sentry error in GitLab. !18878 +- Expose mergeable state of a merge request. !18888 (briankabiro) +- Add ability to select a Cluster management project. !18928 +- Add a Slack slash command to add a comment to an issue. !18946 +- Added installation commands for npm and yarn packages to package detail page. !18999 +- Show start and end dates in Epics list page. !19006 +- Populate new pipeline CI vars from params. !19023 +- Add warnings about pages access control settings. !19067 +- Graphql mutation for (un)subscribing to an epic. !19083 +- API for stack trace & detail view of Sentry error in GitLab. !19137 +- Add grafana integration active status checkbox. !19255 +- GraphQL: Add Merge Request milestone mutation. !19257 +- Add MergeRequestSetAssignees GraphQL mutation. !19272 +- Add edit button to metrics dashboard. !19279 +- Add "release" filter to merge request search page. !19315 +- Add dead jobs to Sidekiq metrics API. !19350 (Marco Peterseil) +- Add pipeline information to dependency list header. !19352 +- Build CI cache key from commit SHAs that changed given files. !19392 +- Adding support for searching tags using '^' and '$'. !19435 (Cauhx Milloy) +- Sentry error stacktrace. !19492 +- Add an `error_code` attribute to the API response when a cherry-pick or revert fails. !19518 +- Add documentation for sign-in application setting. !19561 (Horatiu Eugen Vlad) +- Create AWS EKS cluster. !19578 +- Add modsecurity logging sidecar to ingress controller. !19600 +- Add start a trial option in the top-right user dropdown. !19632 +- Manage and display labels from epic in the GraphQL API. !19642 +- Allow order_by updated_at in Deployments API. !19658 +- Add can_edit and project_blob_path to metrics_dashboard endpoint. !19663 +- Add usage ping data for project services. !19687 +- Graphql query for issues can now be sorted by relative_position. !19713 +- Add API endpoint to trigger Group Structure Export. !19779 +- Show Tree UI containing child Epics and Issues within an Epic. !19812 +- Enable environments dashboard by default. !19838 +- Update the DB schema to allow linking between Vulnerabilities and Issues. !19852 +- Add Group Audit Events API. !19868 +- Adds a copy button next to package metadata on the details page. !19881 +- GraphQL: Create MR mutations needed for the sidebar. !19913 +- Add id_before, id_after filter param to projects API. !19949 +- Add modsecurity feature flag to usage ping. !20194 +- Specify management project for a Kubernetes cluster. !20216 +- Upgrade pages to 1.12.0. !20217 +- Support template_project_id parameter in project creation API. !20258 +- Add heatmap chart support. !32424 +- Add template for Serverless Framework/JS. !33805 + +### Other (59 changes, 26 of them are from the community) + +- Add EKS cluster count to usage data. !17059 +- Track the starting and stopping of the current signup flow and the experimental signup flow. !17521 +- Attribute Sidekiq workers according to their workloads. !18066 +- Add ApplicationSetting entries for EKS integration. !18307 +- Geo: Add resigns-related fields to Geo Node Status table. !18379 +- Allow adding requests to performance bar manually. !18464 +- Removes `export_designs` feature flag. !18507 (nate geslin) +- Update AWS SDK to 2.11.374. !18601 +- Remove required dependecy of Postgresql for Gitaly. !18659 +- Add deployment_merge_requests table. !18755 +- Bump Gitaly to 1.70.0 and remove cache invalidation feature flag. !18766 +- Update gRPC to v1.24.0. !18837 +- Update GitLab Runner Helm Chart to 0.10.0. !18879 +- Adds a Sidekiq queue duration metric. !19005 +- Create explicit Default and Free plans. !19033 +- Improve instance mirroring help text. !19047 +- Add Codesandbox metrics to usage ping. !19075 +- Add internal_socket_dir to gitaly config in setup helper. !19170 +- Use Rails 5.2 Redis caching store. !19202 +- Update GitLab Runner Helm Chart to 0.10.1. !19232 +- Rename snowplow_site_id to snowplow_app_id in application_settings table. !19252 +- Removed IIFEs from network.js file. !19254 (nuwe1) +- Remove IIFEs from project_select.js. !19288 (minghuan lei) +- Remove IIFEs from merge_request.js. !19294 (minghuan lei) +- Make snippet list easier to scan. !19490 +- Removed IIFEs from image_file.js. !19548 (nuwe1) +- Fix api docs for deleting project cluster. !19558 +- Change blob edit view button styling. !19566 +- Include exception and backtrace in API logs. !19671 +- Add index on marked_for_deletion_at in projects table. !19788 +- Visual design for edit buttons in blob view. !19932 +- Refactor disabled sidebar notifications to Vue. !20007 (minghuan lei) +- Remove IIFEs from branch_graph.js. !20008 (minghuan lei) +- Remove IIFEs from new_branch_form.js. !20009 (minghuan lei) +- Remove duplication from slugifyWithUnderscore function. !20016 (Arun Kumar Mohan) +- Update registry.gitlab.com/gitlab-org/security-products/codequality to 12-5-stable. !20046 (Takuya Noguchi) +- Add mb-2 class to global alerts. !20081 (2knal) +- Remove var from syntax_highlight_spec.js. !20086 (Lee Tickett) +- Remove var from merge_request_tabs_spec.js. !20087 (Lee Tickett) +- Remove var from bootstrap_jquery_spec.js. !20089 (Lee Tickett) +- Remove var from project_select.js. !20091 (Lee Tickett) +- Remove var from new_commit_form.js. !20095 (Lee Tickett) +- Remove var from issue.js. !20098 (Lee Tickett) +- Remove var from new_branch_form.js. !20099 (Lee Tickett) +- Remove var from tree.js. !20103 (Lee Tickett) +- Remove var from line_highlighter.js. !20108 (Lee Tickett) +- Remove var from preview_markdown.js. !20115 (Lee Tickett) +- remove all references of BoardService in boards_selector.vue. !20147 (nuwe1) +- Remove all references to BoardsService in index.vue. !20152 (nuwe1) +- Remove var from labels_select.js. !20153 (Lee Tickett) +- Remove all reference to BoardService in board_form.vue. !20158 (nuwe1) +- Remove calendar icon from personal access tokens. !20183 +- Move margin-top from flash container to flash. !20211 +- Bump Auto DevOps deploy image to v0.7.0. !20250 +- Make 'Sidekiq::Testing.fake!' mode as default. !31662 (@blackst0ne) +- Replace task-done icon with list-task icon to better align with other toolbar list icons. +- Dependency Scanning template that doesn't rely on Docker-in-Docker. +- Adding dropdown arrow icon and updated text alignment. +- Change selects from default browser style to custom style. ## 12.4.2 diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 737e2ba509..22d6771a47 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -1.67.1 +1.72.1 diff --git a/GITLAB_ELASTICSEARCH_INDEXER_VERSION b/GITLAB_ELASTICSEARCH_INDEXER_VERSION index 88c5fb891d..bc80560fad 100644 --- a/GITLAB_ELASTICSEARCH_INDEXER_VERSION +++ b/GITLAB_ELASTICSEARCH_INDEXER_VERSION @@ -1 +1 @@ -1.4.0 +1.5.0 diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION index 1cac385c6c..0eed1a29ef 100644 --- a/GITLAB_PAGES_VERSION +++ b/GITLAB_PAGES_VERSION @@ -1 +1 @@ -1.11.0 +1.12.0 diff --git a/Gemfile b/Gemfile index 920f778c05..d27bc27608 100644 --- a/Gemfile +++ b/Gemfile @@ -8,12 +8,12 @@ gem 'bootsnap', '~> 1.4' gem 'nakayoshi_fork', '~> 0.0.4' # Responders respond_to and respond_with -gem 'responders', '~> 2.0' +gem 'responders', '~> 3.0' gem 'sprockets', '~> 3.7.0' # Default values for AR models -gem 'default_value_for', '~> 3.2.0' +gem 'default_value_for', '~> 3.3.0' # Supported DBs gem 'pg', '~> 1.1' @@ -42,7 +42,7 @@ gem 'omniauth-shibboleth', '~> 1.3.0' gem 'omniauth-twitter', '~> 1.4' gem 'omniauth_crowd', '~> 2.2.0' gem 'omniauth-authentiq', '~> 0.3.3' -gem 'omniauth_openid_connect', '~> 0.3.1' +gem 'omniauth_openid_connect', '~> 0.3.3' gem "omniauth-ultraauth", '~> 0.0.2' gem 'omniauth-salesforce', '~> 1.0.5' gem 'rack-oauth2', '~> 1.9.3' @@ -64,7 +64,7 @@ gem 'u2f', '~> 0.2.1' # GitLab Pages gem 'validates_hostname', '~> 1.0.6' -gem 'rubyzip', '~> 1.2.2', require: 'zip' +gem 'rubyzip', '~> 1.3.0', require: 'zip' # GitLab Pages letsencrypt support gem 'acme-client', '~> 2.0.2' @@ -72,7 +72,7 @@ gem 'acme-client', '~> 2.0.2' gem 'browser', '~> 2.5' # GPG -gem 'gpgme', '~> 2.0.18' +gem 'gpgme', '~> 2.0.19' # LDAP Auth # GitLab fork with several improvements to original library. For full list of changes @@ -136,7 +136,7 @@ gem 'faraday_middleware-aws-signers-v4' # Markdown and HTML processing gem 'html-pipeline', '~> 2.8' -gem 'deckar01-task_list', '2.2.0' +gem 'deckar01-task_list', '2.2.1' gem 'gitlab-markup', '~> 1.7.0' gem 'github-markup', '~> 1.7.0', require: 'github/markup' gem 'commonmarker', '~> 0.17' @@ -151,7 +151,7 @@ gem 'asciidoctor-plantuml', '0.0.9' gem 'rouge', '~> 3.11.0' gem 'truncato', '~> 0.7.11' gem 'bootstrap_form', '~> 4.2.0' -gem 'nokogiri', '~> 1.10.4' +gem 'nokogiri', '~> 1.10.5' gem 'escape_utils', '~> 1.1' # Calendar rendering @@ -159,6 +159,7 @@ gem 'icalendar' # Diffs gem 'diffy', '~> 3.1.0' +gem 'diff_match_patch', '~> 0.1.0' # Application server gem 'rack', '~> 2.0.7' @@ -175,7 +176,7 @@ group :puma do end # State machine -gem 'state_machines-activerecord', '~> 0.5.1' +gem 'state_machines-activerecord', '~> 0.6.0' # Issue tags gem 'acts-as-taggable-on', '~> 6.0' @@ -259,9 +260,6 @@ gem 'loofah', '~> 2.2' # Working with license gem 'licensee', '~> 8.9' -# Protect against bruteforcing -gem 'rack-attack', '~> 4.4.1' - # Ace editor gem 'ace-rails-ap', '~> 4.1.0' @@ -293,10 +291,13 @@ gem 'base32', '~> 0.3.0' gem "gitlab-license", "~> 1.0" +# Protect against bruteforcing +gem 'rack-attack', '~> 6.2.0' + # Sentry integration gem 'sentry-raven', '~> 2.9' -gem 'premailer-rails', '~> 1.9.7' +gem 'premailer-rails', '~> 1.10.3' # LabKit: Tracing and Correlation gem 'gitlab-labkit', '~> 0.5' @@ -331,7 +332,6 @@ group :metrics do end group :development do - gem 'foreman', '~> 0.84.0' gem 'brakeman', '~> 4.2', require: false gem 'danger', '~> 6.0', require: false @@ -388,7 +388,6 @@ group :development, :test do gem 'benchmark-ips', '~> 2.3.0', require: false - gem 'license_finder', '~> 5.4', require: false gem 'knapsack', '~> 1.17' gem 'stackprof', '~> 0.2.10', require: false @@ -398,6 +397,11 @@ group :development, :test do gem 'timecop', '~> 0.8.0' end +# Gems required in omnibus-gitlab pipeline +group :development, :test, :omnibus do + gem 'license_finder', '~> 5.4', require: false +end + group :test do gem 'shoulda-matchers', '~> 4.0.1', require: false gem 'email_spec', '~> 2.2.0' @@ -407,6 +411,7 @@ group :test do gem 'concurrent-ruby', '~> 1.1' gem 'test-prof', '~> 0.10.0' gem 'rspec_junit_formatter' + gem 'guard-rspec' end gem 'octokit', '~> 4.9' @@ -446,18 +451,18 @@ group :ed25519 do end # Gitaly GRPC protocol definitions -gem 'gitaly', '~> 1.65.0' +gem 'gitaly', '~> 1.70.0' -gem 'grpc', '~> 1.19.0' +gem 'grpc', '~> 1.24.0' -gem 'google-protobuf', '~> 3.7.1' +gem 'google-protobuf', '~> 3.8.0' gem 'toml-rb', '~> 1.0.0', require: false # Feature toggles -gem 'flipper', '~> 0.13.0' -gem 'flipper-active_record', '~> 0.13.0' -gem 'flipper-active_support_cache_store', '~> 0.13.0' +gem 'flipper', '~> 0.17.1' +gem 'flipper-active_record', '~> 0.17.1' +gem 'flipper-active_support_cache_store', '~> 0.17.1' gem 'unleash', '~> 0.1.5' # Structured logging @@ -469,3 +474,5 @@ gem 'gitlab-net-dns', '~> 0.9.1' # Countries list gem 'countries', '~> 3.0' + +gem 'retriable', '~> 3.1.2' diff --git a/Gemfile.lock b/Gemfile.lock index 18160932c5..15465cd6b0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -50,8 +50,8 @@ GEM i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) - acts-as-taggable-on (6.0.0) - activerecord (~> 5.0) + acts-as-taggable-on (6.5.0) + activerecord (>= 5.0, < 6.1) adamantium (0.2.0) ice_nine (~> 0.11.0) memoizable (~> 0.4.0) @@ -80,14 +80,16 @@ GEM encryptor (~> 3.0.0) attr_required (1.0.1) awesome_print (1.8.0) - aws-sdk (2.9.32) - aws-sdk-resources (= 2.9.32) - aws-sdk-core (2.9.32) + aws-eventstream (1.0.3) + aws-sdk (2.11.374) + aws-sdk-resources (= 2.11.374) + aws-sdk-core (2.11.374) aws-sigv4 (~> 1.0) jmespath (~> 1.0) - aws-sdk-resources (2.9.32) - aws-sdk-core (= 2.9.32) - aws-sigv4 (1.0.0) + aws-sdk-resources (2.11.374) + aws-sdk-core (= 2.11.374) + aws-sigv4 (1.1.0) + aws-eventstream (~> 1.0, >= 1.0.2) axiom-types (0.1.1) descendants_tracker (~> 0.0.4) ice_nine (~> 0.11.0) @@ -171,9 +173,9 @@ GEM unicode_utils (~> 1.4) crack (0.4.3) safe_yaml (~> 1.0.0) - crass (1.0.4) + crass (1.0.5) creole (0.5.0) - css_parser (1.5.0) + css_parser (1.7.0) addressable daemons (1.2.6) danger (6.0.9) @@ -192,12 +194,12 @@ GEM database_cleaner (1.7.0) debug_inspector (0.0.3) debugger-ruby_core_source (1.3.8) - deckar01-task_list (2.2.0) + deckar01-task_list (2.2.1) html-pipeline declarative (0.0.10) declarative-option (0.1.0) - default_value_for (3.2.0) - activerecord (>= 3.2.0, < 6.0) + default_value_for (3.3.0) + activerecord (>= 3.2.0, < 6.1) derailed_benchmarks (1.3.5) benchmark-ips (~> 2) get_process_mem (~> 0) @@ -222,6 +224,7 @@ GEM railties rotp (~> 2.0) diff-lcs (1.3) + diff_match_patch (0.1.0) diffy (3.1.0) discordrb-webhooks-blackst0ne (3.3.0) rest-client (~> 2.0) @@ -285,13 +288,13 @@ GEM fast_gettext (1.6.0) ffaker (2.10.0) ffi (1.11.1) - flipper (0.13.0) - flipper-active_record (0.13.0) - activerecord (>= 3.2, < 6) - flipper (~> 0.13.0) - flipper-active_support_cache_store (0.13.0) - activesupport (>= 3.2, < 6) - flipper (~> 0.13.0) + flipper (0.17.1) + flipper-active_record (0.17.1) + activerecord (>= 4.2, < 7) + flipper (~> 0.17.1) + flipper-active_support_cache_store (0.17.1) + activesupport (>= 4.2, < 7) + flipper (~> 0.17.1) flowdock (0.7.1) httparty (~> 0.7) multi_json @@ -332,10 +335,8 @@ GEM fog-xml (0.1.3) fog-core nokogiri (>= 1.5.11, < 2.0.0) - font-awesome-rails (4.7.0.4) - railties (>= 3.2, < 6.0) - foreman (0.84.0) - thor (~> 0.19.1) + font-awesome-rails (4.7.0.5) + railties (>= 3.2, < 6.1) formatador (0.2.5) fugit (1.2.1) et-orbi (~> 1.1, >= 1.1.8) @@ -358,12 +359,12 @@ GEM po_to_json (>= 1.0.0) rails (>= 3.2.0) git (1.5.0) - gitaly (1.65.0) + gitaly (1.70.0) grpc (~> 1.0) github-markup (1.7.0) - gitlab-labkit (0.5.2) - actionpack (~> 5) - activesupport (~> 5) + gitlab-labkit (0.7.0) + actionpack (>= 5.0.0, < 6.1.0) + activesupport (>= 5.0.0, < 6.1.0) grpc (~> 1.19) jaeger-client (~> 0.10) opentracing (~> 0.4) @@ -400,7 +401,7 @@ GEM mime-types (~> 3.0) representable (~> 3.0) retriable (>= 2.0, < 4.0) - google-protobuf (3.7.1) + google-protobuf (3.8.0) googleapis-common-protos-types (1.0.4) google-protobuf (~> 3.0) googleauth (0.6.6) @@ -410,7 +411,7 @@ GEM multi_json (~> 1.11) os (>= 0.9, < 2.0) signet (~> 0.7) - gpgme (2.0.18) + gpgme (2.0.19) mini_portile2 (~> 2.3) grape (1.1.0) activesupport @@ -440,11 +441,25 @@ GEM graphql (~> 1.6) html-pipeline (~> 2.8) sass (~> 3.4) - grpc (1.19.0) - google-protobuf (~> 3.1) - googleapis-common-protos-types (~> 1.0.0) + grpc (1.24.0) + google-protobuf (~> 3.8) + googleapis-common-protos-types (~> 1.0) gssapi (1.2.0) ffi (>= 1.0.1) + guard (2.15.1) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.0) + lumberjack (>= 1.0.12, < 2.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.9.12) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-compat (1.2.1) + guard-rspec (4.7.3) + guard (~> 2.1) + guard-compat (~> 1.1) + rspec (>= 2.99.0, < 4.0) haml (5.0.4) temple (>= 0.8.0) tilt @@ -508,7 +523,7 @@ GEM atlassian-jwt multipart-post oauth (~> 0.5, >= 0.5.0) - jmespath (1.3.1) + jmespath (1.4.0) js_regex (3.1.1) character_set (~> 1.1) regexp_parser (~> 1.1) @@ -560,15 +575,20 @@ GEM xml-simple licensee (8.9.2) rugged (~> 0.24) + listen (3.1.5) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + ruby_dep (~> 1.2) locale (2.1.2) lograge (0.10.0) actionpack (>= 4) activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.3.0) + loofah (2.3.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) + lumberjack (1.0.13) mail (2.7.1) mini_mime (>= 0.1.1) mail_room (0.9.1) @@ -584,7 +604,7 @@ GEM mime-types-data (3.2019.0331) mimemagic (0.3.2) mini_magick (4.9.5) - mini_mime (1.0.1) + mini_mime (1.0.2) mini_portile2 (2.4.0) minitest (5.11.3) msgpack (1.3.1) @@ -597,16 +617,20 @@ GEM mustermann (~> 1.0.0) nakayoshi_fork (0.0.4) nap (1.1.0) + nenv (0.3.0) net-ldap (0.16.0) net-ntp (2.1.3) net-ssh (5.2.0) netrc (0.11.0) nio4r (2.3.1) no_proxy_fix (0.1.2) - nokogiri (1.10.4) + nokogiri (1.10.5) mini_portile2 (~> 2.4.0) nokogumbo (1.5.0) nokogiri + notiffany (0.1.3) + nenv (~> 0.1) + shellany (~> 0.0) numerizer (0.1.1) oauth (0.5.4) oauth2 (1.4.1) @@ -675,12 +699,12 @@ GEM activesupport nokogiri (>= 1.4.4) omniauth (~> 1.0) - omniauth_openid_connect (0.3.1) + omniauth_openid_connect (0.3.3) addressable (~> 2.5) - omniauth (~> 1.3) + omniauth (~> 1.9) openid_connect (~> 1.1) open4 (1.3.4) - openid_connect (1.1.6) + openid_connect (1.1.8) activemodel attr_required (>= 1.0.0) json-jwt (>= 1.5.0) @@ -703,12 +727,12 @@ GEM pg (1.1.4) po_to_json (1.0.1) json (>= 1.6.0) - premailer (1.10.4) + premailer (1.11.1) addressable - css_parser (>= 1.4.10) + css_parser (>= 1.6.0) htmlentities (>= 4.0.0) - premailer-rails (1.9.7) - actionmailer (>= 3, < 6) + premailer-rails (1.10.3) + actionmailer (>= 3) premailer (~> 1.7, >= 1.7.9) proc_to_ast (0.1.0) coderay @@ -724,7 +748,7 @@ GEM pry (~> 0.10) pry-rails (0.3.6) pry (>= 0.10.4) - public_suffix (3.1.0) + public_suffix (3.1.1) puma (3.12.0) puma_worker_killer (0.1.0) get_process_mem (~> 0.2) @@ -734,8 +758,8 @@ GEM rack (2.0.7) rack-accept (0.4.5) rack (>= 0.4) - rack-attack (4.4.1) - rack + rack-attack (6.2.0) + rack (>= 1.0, < 3) rack-cors (1.0.2) rack-oauth2 (1.9.3) activesupport @@ -763,10 +787,10 @@ GEM bundler (>= 1.3.0) railties (= 5.2.3) sprockets-rails (>= 2.0.0) - rails-controller-testing (1.0.2) - actionpack (~> 5.x, >= 5.0.1) - actionview (~> 5.x, >= 5.0.1) - activesupport (~> 5.x) + rails-controller-testing (1.0.4) + actionpack (>= 5.0.1.x) + actionview (>= 5.0.1.x) + activesupport (>= 5.0.1.x) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) @@ -798,25 +822,25 @@ GEM recaptcha (4.13.1) json recursive-open-struct (1.1.0) - redis (4.1.2) - redis-actionpack (5.0.2) - actionpack (>= 4.0, < 6) + redis (4.1.3) + redis-actionpack (5.1.0) + actionpack (>= 4.0, < 7) redis-rack (>= 1, < 3) redis-store (>= 1.1.0, < 2) - redis-activesupport (5.0.7) - activesupport (>= 3, < 6) + redis-activesupport (5.2.0) + activesupport (>= 3, < 7) redis-store (>= 1.3, < 2) redis-namespace (1.6.0) redis (>= 3.0.4) - redis-rack (2.0.5) + redis-rack (2.0.6) rack (>= 1.5, < 3) redis-store (>= 1.2, < 2) redis-rails (5.0.2) redis-actionpack (>= 5.0, < 6) redis-activesupport (>= 5.0, < 6) redis-store (>= 1.2, < 2) - redis-store (1.6.0) - redis (>= 2.2, < 5) + redis-store (1.8.1) + redis (>= 4, < 5) regexp_parser (1.5.1) regexp_property_values (0.3.4) representable (3.0.4) @@ -824,9 +848,9 @@ GEM declarative-option (< 0.2.0) uber (< 0.2.0) request_store (1.3.1) - responders (2.4.1) - actionpack (>= 4.2.0, < 6.0) - railties (>= 4.2.0, < 6.0) + responders (3.0.0) + actionpack (>= 5.0) + railties (>= 5.0) rest-client (2.0.2) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) @@ -897,11 +921,12 @@ GEM ruby-progressbar (1.10.1) ruby-saml (1.7.2) nokogiri (>= 1.5.10) + ruby_dep (1.5.0) ruby_parser (3.13.1) sexp_processor (~> 4.9) rubyntlm (0.6.2) rubypants (0.2.0) - rubyzip (1.2.2) + rubyzip (1.3.0) rugged (0.28.3.1) safe_yaml (1.0.4) sanitize (4.6.6) @@ -938,6 +963,7 @@ GEM faraday (>= 0.7.6, < 1.0) settingslogic (2.0.9) sexp_processor (4.12.0) + shellany (0.0.1) shoulda-matchers (4.0.1) activesupport (>= 4.2.0) sidekiq (5.2.7) @@ -978,11 +1004,11 @@ GEM sshkey (2.0.0) stackprof (0.2.10) state_machines (0.5.0) - state_machines-activemodel (0.5.1) - activemodel (>= 4.1, < 6.0) + state_machines-activemodel (0.7.1) + activemodel (>= 4.1) state_machines (>= 0.5.0) - state_machines-activerecord (0.5.1) - activerecord (>= 4.1, < 6.0) + state_machines-activerecord (0.6.0) + activerecord (>= 4.1) state_machines-activemodel (>= 0.5.0) swd (1.1.2) activesupport (>= 3) @@ -1127,12 +1153,13 @@ DEPENDENCIES creole (~> 0.5.0) danger (~> 6.0) database_cleaner (~> 1.7.0) - deckar01-task_list (= 2.2.0) - default_value_for (~> 3.2.0) + deckar01-task_list (= 2.2.1) + default_value_for (~> 3.3.0) derailed_benchmarks device_detector devise (~> 4.6) devise-two-factor (~> 3.0.0) + diff_match_patch (~> 0.1.0) diffy (~> 3.1.0) discordrb-webhooks-blackst0ne (~> 3.3) doorkeeper (~> 4.3) @@ -1149,9 +1176,9 @@ DEPENDENCIES faraday_middleware-aws-signers-v4 fast_blank ffaker (~> 2.10) - flipper (~> 0.13.0) - flipper-active_record (~> 0.13.0) - flipper-active_support_cache_store (~> 0.13.0) + flipper (~> 0.17.1) + flipper-active_record (~> 0.17.1) + flipper-active_support_cache_store (~> 0.17.1) flowdock (~> 0.7) fog-aliyun (~> 0.3) fog-aws (~> 3.5) @@ -1161,14 +1188,13 @@ DEPENDENCIES fog-openstack (~> 1.0) fog-rackspace (~> 0.1.1) font-awesome-rails (~> 4.7) - foreman (~> 0.84.0) fugit (~> 1.2.1) fuubar (~> 2.2.0) gemojione (~> 3.3) gettext (~> 3.2.2) gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails_js (~> 1.3) - gitaly (~> 1.65.0) + gitaly (~> 1.70.0) github-markup (~> 1.7.0) gitlab-labkit (~> 0.5) gitlab-license (~> 1.0) @@ -1181,8 +1207,8 @@ DEPENDENCIES gitlab_omniauth-ldap (~> 2.1.1) gon (~> 6.2) google-api-client (~> 0.23) - google-protobuf (~> 3.7.1) - gpgme (~> 2.0.18) + google-protobuf (~> 3.8.0) + gpgme (~> 2.0.19) grape (~> 1.1.0) grape-entity (~> 0.7.1) grape-path-helpers (~> 1.1) @@ -1190,8 +1216,9 @@ DEPENDENCIES graphiql-rails (~> 1.4.10) graphql (~> 1.9.11) graphql-docs (~> 1.6.0) - grpc (~> 1.19.0) + grpc (~> 1.24.0) gssapi + guard-rspec haml_lint (~> 0.31.0) hamlit (~> 2.8.8) hangouts-chat (~> 0.0.5) @@ -1226,7 +1253,7 @@ DEPENDENCIES net-ldap net-ntp net-ssh (~> 5.2) - nokogiri (~> 1.10.4) + nokogiri (~> 1.10.5) oauth2 (~> 1.4) octokit (~> 4.9) omniauth (~> 1.8) @@ -1246,17 +1273,17 @@ DEPENDENCIES omniauth-twitter (~> 1.4) omniauth-ultraauth (~> 0.0.2) omniauth_crowd (~> 2.2.0) - omniauth_openid_connect (~> 0.3.1) + omniauth_openid_connect (~> 0.3.3) org-ruby (~> 0.9.12) pg (~> 1.1) - premailer-rails (~> 1.9.7) + premailer-rails (~> 1.10.3) prometheus-client-mmap (~> 0.9.10) pry-byebug (~> 3.5.1) pry-rails (~> 0.3.4) puma (~> 3.12) puma_worker_killer rack (~> 2.0.7) - rack-attack (~> 4.4.1) + rack-attack (~> 6.2.0) rack-cors (~> 1.0.0) rack-oauth2 (~> 1.9.3) rack-proxy (~> 0.6.0) @@ -1275,7 +1302,8 @@ DEPENDENCIES redis-namespace (~> 1.6.0) redis-rails (~> 5.0.2) request_store (~> 1.3) - responders (~> 2.0) + responders (~> 3.0) + retriable (~> 3.1.2) rouge (~> 3.11.0) rqrcode-rails3 (~> 0.1.7) rspec-parameterized @@ -1291,7 +1319,7 @@ DEPENDENCIES ruby-prof (~> 1.0.0) ruby-progressbar ruby_parser (~> 3.8) - rubyzip (~> 1.2.2) + rubyzip (~> 1.3.0) rugged (~> 0.28) sanitize (~> 4.6) sassc-rails (~> 2.1.0) @@ -1312,7 +1340,7 @@ DEPENDENCIES sprockets (~> 3.7.0) sshkey (~> 2.0) stackprof (~> 0.2.10) - state_machines-activerecord (~> 0.5.1) + state_machines-activerecord (~> 0.6.0) sys-filesystem (~> 1.1.6) test-prof (~> 0.10.0) thin (~> 1.7.0) diff --git a/Guardfile b/Guardfile new file mode 100644 index 0000000000..8a43f414ca --- /dev/null +++ b/Guardfile @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +# More info at https://github.com/guard/guard#readme + +cmd = ENV['SPRING'] ? 'spring rspec' : 'bundle exec rspec' + +guard :rspec, cmd: cmd do + require "guard/rspec/dsl" + dsl = Guard::RSpec::Dsl.new(self) + + directories %w(app ee lib spec) + + # RSpec files + rspec = dsl.rspec + watch(rspec.spec_helper) { rspec.spec_dir } + watch(rspec.spec_support) { rspec.spec_dir } + watch(rspec.spec_files) + + # Ruby files + ruby = dsl.ruby + dsl.watch_spec_files_for(ruby.lib_files) + + # Rails files + rails = dsl.rails(view_extensions: %w(erb haml slim)) + dsl.watch_spec_files_for(rails.app_files) + dsl.watch_spec_files_for(rails.views) + + watch(rails.controllers) do |m| + [ + rspec.spec.call("routing/#{m[1]}_routing"), + rspec.spec.call("controllers/#{m[1]}_controller") + ] + end + + # Rails config changes + watch(rails.spec_helper) { rspec.spec_dir } + watch(rails.routes) { "#{rspec.spec_dir}/routing" } + watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" } + + # Capybara features specs + watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") } + watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") } +end diff --git a/PROCESS.md b/PROCESS.md index 6bff60bff0..45f28b33a6 100644 --- a/PROCESS.md +++ b/PROCESS.md @@ -79,7 +79,7 @@ star, smile, etc.). Some good tips about code reviews can be found in our Overview and details of feature flag processes in development of GitLab itself is described in [feature flags process documentation](https://docs.gitlab.com/ee/development/feature_flags/process.html). -Guides on how to include feature flags in your backend/frontend code while developing GitLab are described in [developing with feature flags documentation](https://docs.gitlab.com/ee/development/feature_flags/developing.html). +Guides on how to include feature flags in your backend/frontend code while developing GitLab are described in [developing with feature flags documentation](https://docs.gitlab.com/ee/development/feature_flags/development.html). Getting access and how to expose the feature to users is detailed in [controlling feature flags documentation](https://docs.gitlab.com/ee/development/feature_flags/controls.html). diff --git a/VERSION b/VERSION index fc2e27826a..b6125ec500 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -12.4.6 +12.5.4 diff --git a/app/assets/images/cluster_app_logos/crossplane.png b/app/assets/images/cluster_app_logos/crossplane.png new file mode 100644 index 0000000000..32d8175108 Binary files /dev/null and b/app/assets/images/cluster_app_logos/crossplane.png differ diff --git a/app/assets/images/cluster_app_logos/elastic_stack.png b/app/assets/images/cluster_app_logos/elastic_stack.png new file mode 100644 index 0000000000..69fbc6aacd Binary files /dev/null and b/app/assets/images/cluster_app_logos/elastic_stack.png differ diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index 908dc730aa..aee9990bc0 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -2,6 +2,8 @@ import $ from 'jquery'; import _ from 'underscore'; import axios from './lib/utils/axios_utils'; import { joinPaths } from './lib/utils/url_utility'; +import flash from '~/flash'; +import { __ } from '~/locale'; const Api = { groupsPath: '/api/:version/groups.json', @@ -29,6 +31,7 @@ const Api = { usersPath: '/api/:version/users.json', userPath: '/api/:version/users/:id', userStatusPath: '/api/:version/users/:id/status', + userProjectsPath: '/api/:version/users/:id/projects', userPostStatusPath: '/api/:version/user/status', commitPath: '/api/:version/projects/:id/repository/commits', applySuggestionPath: '/api/:version/suggestions/:id/apply', @@ -110,10 +113,9 @@ const Api = { .get(url, { params: Object.assign(defaults, options), }) - .then(({ data }) => { + .then(({ data, headers }) => { callback(data); - - return data; + return { data, headers }; }); }, @@ -239,7 +241,8 @@ const Api = { .get(url, { params: Object.assign({}, defaults, options), }) - .then(({ data }) => callback(data)); + .then(({ data }) => callback(data)) + .catch(() => flash(__('Something went wrong while fetching projects'))); }, commitMultiple(id, data) { @@ -348,6 +351,20 @@ const Api = { }); }, + userProjects(userId, query, options, callback) { + const url = Api.buildUrl(Api.userProjectsPath).replace(':id', userId); + const defaults = { + search: query, + per_page: 20, + }; + return axios + .get(url, { + params: Object.assign({}, defaults, options), + }) + .then(({ data }) => callback(data)) + .catch(() => flash(__('Something went wrong while fetching projects'))); + }, + branches(id, query = '', options = {}) { const url = Api.buildUrl(this.createBranchPath).replace(':id', encodeURIComponent(id)); diff --git a/app/assets/javascripts/behaviors/preview_markdown.js b/app/assets/javascripts/behaviors/preview_markdown.js index a07942d87c..ca91400eac 100644 --- a/app/assets/javascripts/behaviors/preview_markdown.js +++ b/app/assets/javascripts/behaviors/preview_markdown.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, no-var */ +/* eslint-disable func-names */ import $ from 'jquery'; import axios from '~/lib/utils/axios_utils'; @@ -12,11 +12,8 @@ import { __ } from '~/locale'; // more than `x` users are referenced. // -var lastTextareaPreviewed; -var lastTextareaHeight = null; -var markdownPreview; -var previewButtonSelector; -var writeButtonSelector; +let lastTextareaHeight; +let lastTextareaPreviewed; function MarkdownPreview() {} @@ -27,14 +24,13 @@ MarkdownPreview.prototype.emptyMessage = __('Nothing to preview.'); MarkdownPreview.prototype.ajaxCache = {}; MarkdownPreview.prototype.showPreview = function($form) { - var mdText; - var preview = $form.find('.js-md-preview'); - var url = preview.data('url'); + const preview = $form.find('.js-md-preview'); + const url = preview.data('url'); if (preview.hasClass('md-preview-loading')) { return; } - mdText = $form.find('textarea.markdown-area').val(); + const mdText = $form.find('textarea.markdown-area').val(); if (mdText === undefined) { return; @@ -46,7 +42,7 @@ MarkdownPreview.prototype.showPreview = function($form) { } else { preview.addClass('md-preview-loading').text(__('Loading...')); this.fetchMarkdownPreview(mdText, url, response => { - var body; + let body; if (response.body.length > 0) { ({ body } = response); } else { @@ -91,8 +87,7 @@ MarkdownPreview.prototype.hideReferencedUsers = function($form) { }; MarkdownPreview.prototype.renderReferencedUsers = function(users, $form) { - var referencedUsers; - referencedUsers = $form.find('.referenced-users'); + const referencedUsers = $form.find('.referenced-users'); if (referencedUsers.length) { if (users.length >= this.referenceThreshold) { referencedUsers.show(); @@ -108,8 +103,7 @@ MarkdownPreview.prototype.hideReferencedCommands = function($form) { }; MarkdownPreview.prototype.renderReferencedCommands = function(commands, $form) { - var referencedCommands; - referencedCommands = $form.find('.referenced-commands'); + const referencedCommands = $form.find('.referenced-commands'); if (commands.length > 0) { referencedCommands.html(commands); referencedCommands.show(); @@ -119,15 +113,15 @@ MarkdownPreview.prototype.renderReferencedCommands = function(commands, $form) { } }; -markdownPreview = new MarkdownPreview(); +const markdownPreview = new MarkdownPreview(); -previewButtonSelector = '.js-md-preview-button'; -writeButtonSelector = '.js-md-write-button'; +const previewButtonSelector = '.js-md-preview-button'; +const writeButtonSelector = '.js-md-write-button'; lastTextareaPreviewed = null; const markdownToolbar = $('.md-header-toolbar'); $.fn.setupMarkdownPreview = function() { - var $form = $(this); + const $form = $(this); $form.find('textarea.markdown-area').on('input', () => { markdownPreview.hideReferencedUsers($form); }); @@ -188,7 +182,7 @@ $(document).on('markdown-preview:hide', (e, $form) => { }); $(document).on('markdown-preview:toggle', (e, keyboardEvent) => { - var $target; + let $target; $target = $(keyboardEvent.target); if ($target.is('textarea.markdown-area')) { $(document).triggerHandler('markdown-preview:show', [$target.closest('form')]); @@ -201,16 +195,14 @@ $(document).on('markdown-preview:toggle', (e, keyboardEvent) => { }); $(document).on('click', previewButtonSelector, function(e) { - var $form; e.preventDefault(); - $form = $(this).closest('form'); + const $form = $(this).closest('form'); $(document).triggerHandler('markdown-preview:show', [$form]); }); $(document).on('click', writeButtonSelector, function(e) { - var $form; e.preventDefault(); - $form = $(this).closest('form'); + const $form = $(this).closest('form'); $(document).triggerHandler('markdown-preview:hide', [$form]); }); diff --git a/app/assets/javascripts/blob/file_template_mediator.js b/app/assets/javascripts/blob/file_template_mediator.js index b371f6be26..aedd8004ea 100644 --- a/app/assets/javascripts/blob/file_template_mediator.js +++ b/app/assets/javascripts/blob/file_template_mediator.js @@ -118,8 +118,6 @@ export default class FileTemplateMediator { } }); - this.setFilename(item.name); - if (this.editor.getValue() !== '') { this.setTypeSelectorToggleText(item.name); } @@ -133,14 +131,16 @@ export default class FileTemplateMediator { selectTemplateFile(selector, query, data) { const self = this; + const { name } = selector.config; selector.renderLoading(); this.fetchFileTemplate(selector.config.type, query, data) .then(file => { this.setEditorContent(file); + this.setFilename(name); selector.renderLoaded(); - this.typeSelector.setToggleText(selector.config.name); + this.typeSelector.setToggleText(name); toast(__(`${query} template applied`), { action: { text: __('Undo'), diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue index 3456056075..c0df8b7209 100644 --- a/app/assets/javascripts/boards/components/board_form.vue +++ b/app/assets/javascripts/boards/components/board_form.vue @@ -133,7 +133,7 @@ export default { if (this.board.name.length === 0) return; this.isLoading = true; if (this.isDeleteForm) { - gl.boardService + boardsStore .deleteBoard(this.currentBoard) .then(() => { visitUrl(boardsStore.rootPath); @@ -143,7 +143,7 @@ export default { this.isLoading = false; }); } else { - gl.boardService + boardsStore .createBoard(this.board) .then(resp => resp.data) .then(data => { diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue index 1273fcc6a9..b8439bc874 100644 --- a/app/assets/javascripts/boards/components/board_list.vue +++ b/app/assets/javascripts/boards/components/board_list.vue @@ -84,7 +84,8 @@ export default { this.$nextTick(() => { if ( this.scrollHeight() <= this.listHeight() && - this.list.issuesSize > this.list.issues.length + this.list.issuesSize > this.list.issues.length && + this.list.isExpanded ) { this.list.page += 1; this.list.getIssues(false).catch(() => { diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue index 334c162954..32491dfbcb 100644 --- a/app/assets/javascripts/boards/components/boards_selector.vue +++ b/app/assets/javascripts/boards/components/boards_selector.vue @@ -168,7 +168,7 @@ export default { } const recentBoardsPromise = new Promise((resolve, reject) => - gl.boardService + boardsStore .recentBoards() .then(resolve) .catch(err => { @@ -184,7 +184,7 @@ export default { }), ); - Promise.all([gl.boardService.allBoards(), recentBoardsPromise]) + Promise.all([boardsStore.allBoards(), recentBoardsPromise]) .then(([allBoards, recentBoards]) => [allBoards.data, recentBoards.data]) .then(([allBoardsJson, recentBoardsJson]) => { this.loading = false; diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue index 40d75d53f7..d37e49bab4 100644 --- a/app/assets/javascripts/boards/components/issue_card_inner.vue +++ b/app/assets/javascripts/boards/components/issue_card_inner.vue @@ -1,5 +1,6 @@ @@ -217,7 +265,7 @@ export default {

{{ s__(`ClusterIntegration|Choose which applications to install on your Kubernetes cluster. - Helm Tiller is required to install any of the following applications.`) + Helm Tiller is required to install any of the following applications.`) }} {{ __('More information') }}

@@ -242,9 +290,9 @@ export default {
{{ s__(`ClusterIntegration|Helm streamlines installing - and managing Kubernetes applications. - Tiller runs inside of your Kubernetes Cluster, - and manages releases of your charts.`) + and managing Kubernetes applications. + Tiller runs inside of your Kubernetes Cluster, + and manages releases of your charts.`) }}
@@ -252,7 +300,7 @@ export default {
{{ s__(`ClusterIntegration|You must first install Helm Tiller before - installing the applications below`) + installing the applications below`) }} {{ s__(`ClusterIntegration|Ingress gives you a way to route - requests to services based on the request host or path, - centralizing a number of services into a single entrypoint.`) + requests to services based on the request host or path, + centralizing a number of services into a single entrypoint.`) }}

@@ -308,8 +356,8 @@ export default {

{{ s__(`ClusterIntegration|Point a wildcard DNS to this - generated endpoint in order to access - your application after it has been deployed.`) + generated endpoint in order to access + your application after it has been deployed.`) }} {{ __('More information') }} @@ -320,8 +368,8 @@ export default {

{{ s__(`ClusterIntegration|The endpoint is in - the process of being assigned. Please check your Kubernetes - cluster or Quotas on Google Kubernetes Engine if it takes a long time.`) + the process of being assigned. Please check your Kubernetes + cluster or Quotas on Google Kubernetes Engine if it takes a long time.`) }} {{ __('More information') }} @@ -368,7 +416,7 @@ export default {

{{ s__(`ClusterIntegration|Issuers represent a certificate authority. - You must provide an email address for your Issuer. `) + You must provide an email address for your Issuer. `) }} {{ s__(`ClusterIntegration|GitLab Runner connects to the - repository and executes CI/CD jobs, - pushing results back and deploying - applications to production.`) + repository and executes CI/CD jobs, + pushing results back and deploying + applications to production.`) }} + + + + {{ s__(`ClusterIntegration|JupyterHub, a multi-user Hub, spawns, - manages, and proxies multiple instances of the single-user - Jupyter notebook server. JupyterHub can be used to serve - notebooks to a class of students, a corporate data science group, - or a scientific research group.`) + manages, and proxies multiple instances of the single-user + Jupyter notebook server. JupyterHub can be used to serve + notebooks to a class of students, a corporate data science group, + or a scientific research group.`) }}

@@ -481,7 +557,7 @@ export default {

{{ s__(`ClusterIntegration|Replace this with your own hostname if you want. - If you do so, point hostname to Ingress IP Address from above.`) + If you do so, point hostname to Ingress IP Address from above.`) }} {{ __('More information') }} @@ -527,9 +603,9 @@ export default {

{{ s__(`ClusterIntegration|Knative extends Kubernetes to provide - a set of middleware components that are essential to build modern, - source-centric, and container-based applications that can run - anywhere: on premises, in the cloud, or even in a third-party data center.`) + a set of middleware components that are essential to build modern, + source-centric, and container-based applications that can run + anywhere: on premises, in the cloud, or even in a third-party data center.`) }}

@@ -542,6 +618,75 @@ export default { />
+ +
+

+ {{ + s__( + `ClusterIntegration|The elastic stack collects logs from all pods in your cluster`, + ) + }} +

+ + +
+
diff --git a/app/assets/javascripts/clusters/components/crossplane_provider_stack.vue b/app/assets/javascripts/clusters/components/crossplane_provider_stack.vue new file mode 100644 index 0000000000..966918ae63 --- /dev/null +++ b/app/assets/javascripts/clusters/components/crossplane_provider_stack.vue @@ -0,0 +1,93 @@ + + + diff --git a/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue b/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue index f1925c243f..125bcaacc1 100644 --- a/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue +++ b/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue @@ -2,7 +2,16 @@ import { GlModal } from '@gitlab/ui'; import { sprintf, s__ } from '~/locale'; import trackUninstallButtonClickMixin from 'ee_else_ce/clusters/mixins/track_uninstall_button_click'; -import { HELM, INGRESS, CERT_MANAGER, PROMETHEUS, RUNNER, KNATIVE, JUPYTER } from '../constants'; +import { + HELM, + INGRESS, + CERT_MANAGER, + PROMETHEUS, + RUNNER, + KNATIVE, + JUPYTER, + ELASTIC_STACK, +} from '../constants'; const CUSTOM_APP_WARNING_TEXT = { [HELM]: sprintf( @@ -28,6 +37,7 @@ const CUSTOM_APP_WARNING_TEXT = { [JUPYTER]: s__( 'ClusterIntegration|All data not committed to GitLab will be deleted and cannot be restored.', ), + [ELASTIC_STACK]: s__('ClusterIntegration|All data will be deleted and cannot be restored.'), }; export default { diff --git a/app/assets/javascripts/clusters/constants.js b/app/assets/javascripts/clusters/constants.js index c6e4b7951c..9f98f170fb 100644 --- a/app/assets/javascripts/clusters/constants.js +++ b/app/assets/javascripts/clusters/constants.js @@ -50,8 +50,19 @@ export const JUPYTER = 'jupyter'; export const KNATIVE = 'knative'; export const RUNNER = 'runner'; export const CERT_MANAGER = 'cert_manager'; +export const CROSSPLANE = 'crossplane'; export const PROMETHEUS = 'prometheus'; +export const ELASTIC_STACK = 'elastic_stack'; -export const APPLICATIONS = [HELM, INGRESS, JUPYTER, KNATIVE, RUNNER, CERT_MANAGER, PROMETHEUS]; +export const APPLICATIONS = [ + HELM, + INGRESS, + JUPYTER, + KNATIVE, + RUNNER, + CERT_MANAGER, + PROMETHEUS, + ELASTIC_STACK, +]; export const INGRESS_DOMAIN_SUFFIX = '.nip.io'; diff --git a/app/assets/javascripts/clusters/services/clusters_service.js b/app/assets/javascripts/clusters/services/clusters_service.js index fa12802b3d..333fb293a1 100644 --- a/app/assets/javascripts/clusters/services/clusters_service.js +++ b/app/assets/javascripts/clusters/services/clusters_service.js @@ -7,10 +7,12 @@ export default class ClusterService { helm: this.options.installHelmEndpoint, ingress: this.options.installIngressEndpoint, cert_manager: this.options.installCertManagerEndpoint, + crossplane: this.options.installCrossplaneEndpoint, runner: this.options.installRunnerEndpoint, prometheus: this.options.installPrometheusEndpoint, jupyter: this.options.installJupyterEndpoint, knative: this.options.installKnativeEndpoint, + elastic_stack: this.options.installElasticStackEndpoint, }; this.appUpdateEndpointMap = { knative: this.options.updateKnativeEndpoint, diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js index 6464461ea0..35dbf95155 100644 --- a/app/assets/javascripts/clusters/stores/clusters_store.js +++ b/app/assets/javascripts/clusters/stores/clusters_store.js @@ -5,6 +5,8 @@ import { JUPYTER, KNATIVE, CERT_MANAGER, + ELASTIC_STACK, + CROSSPLANE, RUNNER, APPLICATION_INSTALLED_STATUSES, APPLICATION_STATUS, @@ -25,6 +27,7 @@ const applicationInitialState = { uninstallable: false, uninstallFailed: false, uninstallSuccessful: false, + validationError: null, }; export default class ClusterStore { @@ -57,6 +60,11 @@ export default class ClusterStore { title: s__('ClusterIntegration|Cert-Manager'), email: null, }, + crossplane: { + ...applicationInitialState, + title: s__('ClusterIntegration|Crossplane'), + stack: null, + }, runner: { ...applicationInitialState, title: s__('ClusterIntegration|GitLab Runner'), @@ -85,6 +93,11 @@ export default class ClusterStore { updateSuccessful: false, updateFailed: false, }, + elastic_stack: { + ...applicationInitialState, + title: s__('ClusterIntegration|Elastic Stack'), + kibana_hostname: null, + }, }, environments: [], fetchingEnvironments: false, @@ -197,13 +210,15 @@ export default class ClusterStore { } else if (appId === CERT_MANAGER) { this.state.applications.cert_manager.email = this.state.applications.cert_manager.email || serverAppEntry.email; + } else if (appId === CROSSPLANE) { + this.state.applications.crossplane.stack = + this.state.applications.crossplane.stack || serverAppEntry.stack; } else if (appId === JUPYTER) { - this.state.applications.jupyter.hostname = - this.state.applications.jupyter.hostname || - serverAppEntry.hostname || - (this.state.applications.ingress.externalIp - ? `jupyter.${this.state.applications.ingress.externalIp}.nip.io` - : ''); + this.state.applications.jupyter.hostname = this.updateHostnameIfUnset( + this.state.applications.jupyter.hostname, + serverAppEntry.hostname, + 'jupyter', + ); } else if (appId === KNATIVE) { if (!this.state.applications.knative.isEditingHostName) { this.state.applications.knative.hostname = @@ -216,10 +231,26 @@ export default class ClusterStore { } else if (appId === RUNNER) { this.state.applications.runner.version = version; this.state.applications.runner.updateAvailable = updateAvailable; + } else if (appId === ELASTIC_STACK) { + this.state.applications.elastic_stack.kibana_hostname = this.updateHostnameIfUnset( + this.state.applications.elastic_stack.kibana_hostname, + serverAppEntry.kibana_hostname, + 'kibana', + ); } }); } + updateHostnameIfUnset(current, updated, fallback) { + return ( + current || + updated || + (this.state.applications.ingress.externalIp + ? `${fallback}.${this.state.applications.ingress.externalIp}.nip.io` + : '') + ); + } + toggleFetchEnvironments(isFetching) { this.state.fetchingEnvironments = isFetching; } diff --git a/app/assets/javascripts/commit/image_file.js b/app/assets/javascripts/commit/image_file.js index 6c04e0beb4..60c2059a87 100644 --- a/app/assets/javascripts/commit/image_file.js +++ b/app/assets/javascripts/commit/image_file.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, no-var, no-else-return, consistent-return, one-var, no-return-assign, no-unused-expressions, no-sequences */ +/* eslint-disable func-names, no-var, no-else-return, consistent-return, one-var, no-return-assign */ import $ from 'jquery'; @@ -9,40 +9,29 @@ const viewModes = ['two-up', 'swipe']; export default class ImageFile { constructor(file) { this.file = file; - this.requestImageInfo( - $('.two-up.view .frame.deleted img', this.file), - (function(_this) { - return function() { - return _this.requestImageInfo($('.two-up.view .frame.added img', _this.file), () => { - _this.initViewModes(); + this.requestImageInfo($('.two-up.view .frame.deleted img', this.file), () => + this.requestImageInfo($('.two-up.view .frame.added img', this.file), () => { + this.initViewModes(); - // Load two-up view after images are loaded - // so that we can display the correct width and height information - const $images = $('.two-up.view img', _this.file); + // Load two-up view after images are loaded + // so that we can display the correct width and height information + const $images = $('.two-up.view img', this.file); - $images.waitForImages(() => { - _this.initView('two-up'); - }); - }); - }; - })(this), + $images.waitForImages(() => { + this.initView('two-up'); + }); + }), ); } initViewModes() { const viewMode = viewModes[0]; $('.view-modes', this.file).removeClass('hide'); - $('.view-modes-menu', this.file).on( - 'click', - 'li', - (function(_this) { - return function(event) { - if (!$(event.currentTarget).hasClass('active')) { - return _this.activateViewMode(event.currentTarget.className); - } - }; - })(this), - ); + $('.view-modes-menu', this.file).on('click', 'li', event => { + if (!$(event.currentTarget).hasClass('active')) { + return this.activateViewMode(event.currentTarget.className); + } + }); return this.activateViewMode(viewMode); } @@ -51,15 +40,10 @@ export default class ImageFile { .removeClass('active') .filter(`.${viewMode}`) .addClass('active'); - return $(`.view:visible:not(.${viewMode})`, this.file).fadeOut( - 200, - (function(_this) { - return function() { - $(`.view.${viewMode}`, _this.file).fadeIn(200); - return _this.initView(viewMode); - }; - })(this), - ); + return $(`.view:visible:not(.${viewMode})`, this.file).fadeOut(200, () => { + $(`.view.${viewMode}`, this.file).fadeIn(200); + return this.initView(viewMode); + }); } initView(viewMode) { @@ -103,22 +87,18 @@ export default class ImageFile { .on('touchmove', dragMove); } - prepareFrames(view) { + static prepareFrames(view) { var maxHeight, maxWidth; maxWidth = 0; maxHeight = 0; $('.frame', view) - .each( - (function() { - return function(index, frame) { - var height, width; - width = $(frame).width(); - height = $(frame).height(); - maxWidth = width > maxWidth ? width : maxWidth; - return (maxHeight = height > maxHeight ? height : maxHeight); - }; - })(this), - ) + .each((index, frame) => { + var height, width; + width = $(frame).width(); + height = $(frame).height(); + maxWidth = width > maxWidth ? width : maxWidth; + return (maxHeight = height > maxHeight ? height : maxHeight); + }) .css({ width: maxWidth, height: maxHeight, @@ -128,104 +108,95 @@ export default class ImageFile { views = { 'two-up': function() { - return $('.two-up.view .wrap', this.file).each( - (function(_this) { - return function(index, wrap) { - $('img', wrap).each(function() { - var currentWidth; - currentWidth = $(this).width(); - if (currentWidth > availWidth / 2) { - return $(this).width(availWidth / 2); - } - }); - return _this.requestImageInfo($('img', wrap), (width, height) => { - $('.image-info .meta-width', wrap).text(`${width}px`); - $('.image-info .meta-height', wrap).text(`${height}px`); - return $('.image-info', wrap).removeClass('hide'); - }); - }; - })(this), - ); + return $('.two-up.view .wrap', this.file).each((index, wrap) => { + $('img', wrap).each(function() { + var currentWidth; + currentWidth = $(this).width(); + if (currentWidth > availWidth / 2) { + return $(this).width(availWidth / 2); + } + }); + return this.requestImageInfo($('img', wrap), (width, height) => { + $('.image-info .meta-width', wrap).text(`${width}px`); + $('.image-info .meta-height', wrap).text(`${height}px`); + return $('.image-info', wrap).removeClass('hide'); + }); + }); }, swipe() { var maxHeight, maxWidth; maxWidth = 0; maxHeight = 0; - return $('.swipe.view', this.file).each( - (function(_this) { - return function(index, view) { - var $swipeWrap, $swipeBar, $swipeFrame, wrapPadding, ref; - (ref = _this.prepareFrames(view)), ([maxWidth, maxHeight] = ref); - $swipeFrame = $('.swipe-frame', view); - $swipeWrap = $('.swipe-wrap', view); - $swipeBar = $('.swipe-bar', view); + return $('.swipe.view', this.file).each((index, view) => { + var $swipeWrap, $swipeBar, $swipeFrame, wrapPadding; + const ref = ImageFile.prepareFrames(view); + [maxWidth, maxHeight] = ref; + $swipeFrame = $('.swipe-frame', view); + $swipeWrap = $('.swipe-wrap', view); + $swipeBar = $('.swipe-bar', view); - $swipeFrame.css({ - width: maxWidth + 16, - height: maxHeight + 28, - }); - $swipeWrap.css({ - width: maxWidth + 1, - height: maxHeight + 2, - }); - // Set swipeBar left position to match image frame - $swipeBar.css({ - left: 1, - }); + $swipeFrame.css({ + width: maxWidth + 16, + height: maxHeight + 28, + }); + $swipeWrap.css({ + width: maxWidth + 1, + height: maxHeight + 2, + }); + // Set swipeBar left position to match image frame + $swipeBar.css({ + left: 1, + }); - wrapPadding = parseInt($swipeWrap.css('right').replace('px', ''), 10); + wrapPadding = parseInt($swipeWrap.css('right').replace('px', ''), 10); - _this.initDraggable($swipeBar, wrapPadding, (e, left) => { - if (left > 0 && left < $swipeFrame.width() - wrapPadding * 2) { - $swipeWrap.width(maxWidth + 1 - left); - $swipeBar.css('left', left); - } - }); - }; - })(this), - ); + this.initDraggable($swipeBar, wrapPadding, (e, left) => { + if (left > 0 && left < $swipeFrame.width() - wrapPadding * 2) { + $swipeWrap.width(maxWidth + 1 - left); + $swipeBar.css('left', left); + } + }); + }); }, 'onion-skin': function() { var dragTrackWidth, maxHeight, maxWidth; maxWidth = 0; maxHeight = 0; dragTrackWidth = $('.drag-track', this.file).width() - $('.dragger', this.file).width(); - return $('.onion-skin.view', this.file).each( - (function(_this) { - return function(index, view) { - var $frame, $track, $dragger, $frameAdded, framePadding, ref; - (ref = _this.prepareFrames(view)), ([maxWidth, maxHeight] = ref); - $frame = $('.onion-skin-frame', view); - $frameAdded = $('.frame.added', view); - $track = $('.drag-track', view); - $dragger = $('.dragger', $track); + return $('.onion-skin.view', this.file).each((index, view) => { + var $frame, $track, $dragger, $frameAdded, framePadding; - $frame.css({ - width: maxWidth + 16, - height: maxHeight + 28, - }); - $('.swipe-wrap', view).css({ - width: maxWidth + 1, - height: maxHeight + 2, - }); - $dragger.css({ - left: dragTrackWidth, - }); + const ref = ImageFile.prepareFrames(view); + [maxWidth, maxHeight] = ref; + $frame = $('.onion-skin-frame', view); + $frameAdded = $('.frame.added', view); + $track = $('.drag-track', view); + $dragger = $('.dragger', $track); - $frameAdded.css('opacity', 1); - framePadding = parseInt($frameAdded.css('right').replace('px', ''), 10); + $frame.css({ + width: maxWidth + 16, + height: maxHeight + 28, + }); + $('.swipe-wrap', view).css({ + width: maxWidth + 1, + height: maxHeight + 2, + }); + $dragger.css({ + left: dragTrackWidth, + }); - _this.initDraggable($dragger, framePadding, (e, left) => { - var opacity = left / dragTrackWidth; + $frameAdded.css('opacity', 1); + framePadding = parseInt($frameAdded.css('right').replace('px', ''), 10); - if (opacity >= 0 && opacity <= 1) { - $dragger.css('left', left); - $frameAdded.css('opacity', opacity); - } - }); - }; - })(this), - ); + this.initDraggable($dragger, framePadding, (e, left) => { + var opacity = left / dragTrackWidth; + + if (opacity >= 0 && opacity <= 1) { + $dragger.css('left', left); + $frameAdded.css('opacity', opacity); + } + }); + }); }, }; @@ -235,14 +206,7 @@ export default class ImageFile { if (domImg.complete) { return callback.call(this, domImg.naturalWidth, domImg.naturalHeight); } else { - return img.on( - 'load', - (function(_this) { - return function() { - return callback.call(_this, domImg.naturalWidth, domImg.naturalHeight); - }; - })(this), - ); + return img.on('load', () => callback.call(this, domImg.naturalWidth, domImg.naturalHeight)); } } } diff --git a/app/assets/javascripts/compare_autocomplete.js b/app/assets/javascripts/compare_autocomplete.js index 81ba15577f..a23707209d 100644 --- a/app/assets/javascripts/compare_autocomplete.js +++ b/app/assets/javascripts/compare_autocomplete.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, one-var, no-var, no-else-return */ +/* eslint-disable func-names, no-else-return */ import $ from 'jquery'; import { __ } from './locale'; @@ -8,9 +8,8 @@ import { capitalizeFirstCharacter } from './lib/utils/text_utility'; export default function initCompareAutocomplete(limitTo = null, clickHandler = () => {}) { $('.js-compare-dropdown').each(function() { - var $dropdown, selected; - $dropdown = $(this); - selected = $dropdown.data('selected'); + const $dropdown = $(this); + const selected = $dropdown.data('selected'); const $dropdownContainer = $dropdown.closest('.dropdown'); const $fieldInput = $(`input[name="${$dropdown.data('fieldName')}"]`, $dropdownContainer); const $filterInput = $('input[type="search"]', $dropdownContainer); @@ -44,17 +43,16 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = ( fieldName: $dropdown.data('fieldName'), filterInput: 'input[type="search"]', renderRow(ref) { - var link; + const link = $('
') + .attr('href', '#') + .addClass(ref === selected ? 'is-active' : '') + .text(ref) + .attr('data-ref', ref); if (ref.header != null) { return $('
  • ') .addClass('dropdown-header') .text(ref.header); } else { - link = $('') - .attr('href', '#') - .addClass(ref === selected ? 'is-active' : '') - .text(ref) - .attr('data-ref', ref); return $('
  • ').append(link); } }, diff --git a/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue b/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue index 197a070606..4fa18b1955 100644 --- a/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue +++ b/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue @@ -41,7 +41,7 @@ export default { noForkText() { return sprintf( __( - "To protect this issue's confidentiality, %{link_start}fork the project%{link_end} and set the forks visiblity to private.", + "To protect this issue's confidentiality, %{link_start}fork the project%{link_end} and set the forks visibility to private.", ), { link_start: ``, link_end: '' }, false, diff --git a/app/assets/javascripts/contributors/components/contributors.vue b/app/assets/javascripts/contributors/components/contributors.vue new file mode 100644 index 0000000000..7dd6b051cb --- /dev/null +++ b/app/assets/javascripts/contributors/components/contributors.vue @@ -0,0 +1,227 @@ + + + diff --git a/app/assets/javascripts/contributors/index.js b/app/assets/javascripts/contributors/index.js new file mode 100644 index 0000000000..b606358973 --- /dev/null +++ b/app/assets/javascripts/contributors/index.js @@ -0,0 +1,23 @@ +import Vue from 'vue'; +import ContributorsGraphs from './components/contributors.vue'; +import store from './stores'; + +export default () => { + const el = document.querySelector('.js-contributors-graph'); + + if (!el) return null; + + return new Vue({ + el, + store, + + render(createElement) { + return createElement(ContributorsGraphs, { + props: { + endpoint: el.dataset.projectGraphPath, + branch: el.dataset.projectBranch, + }, + }); + }, + }); +}; diff --git a/app/assets/javascripts/contributors/services/contributors_service.js b/app/assets/javascripts/contributors/services/contributors_service.js new file mode 100644 index 0000000000..5a8bbb6651 --- /dev/null +++ b/app/assets/javascripts/contributors/services/contributors_service.js @@ -0,0 +1,7 @@ +import axios from '~/lib/utils/axios_utils'; + +export default { + fetchChartData(endpoint) { + return axios.get(endpoint); + }, +}; diff --git a/app/assets/javascripts/contributors/stores/actions.js b/app/assets/javascripts/contributors/stores/actions.js new file mode 100644 index 0000000000..4138ff24f1 --- /dev/null +++ b/app/assets/javascripts/contributors/stores/actions.js @@ -0,0 +1,20 @@ +import flash from '~/flash'; +import { __ } from '~/locale'; +import service from '../services/contributors_service'; +import * as types from './mutation_types'; + +export const fetchChartData = ({ commit }, endpoint) => { + commit(types.SET_LOADING_STATE, true); + + return service + .fetchChartData(endpoint) + .then(res => res.data) + .then(data => { + commit(types.SET_CHART_DATA, data); + commit(types.SET_LOADING_STATE, false); + }) + .catch(() => flash(__('An error occurred while loading chart data'))); +}; + +// prevent babel-plugin-rewire from generating an invalid default during karma tests +export default () => {}; diff --git a/app/assets/javascripts/contributors/stores/getters.js b/app/assets/javascripts/contributors/stores/getters.js new file mode 100644 index 0000000000..9e02e3ed9e --- /dev/null +++ b/app/assets/javascripts/contributors/stores/getters.js @@ -0,0 +1,33 @@ +export const showChart = state => Boolean(!state.loading && state.chartData); + +export const parsedData = state => { + const byAuthor = {}; + const total = {}; + + state.chartData.forEach(({ date, author_name, author_email }) => { + total[date] = total[date] ? total[date] + 1 : 1; + + const authorData = byAuthor[author_name]; + + if (!authorData) { + byAuthor[author_name] = { + email: author_email.toLowerCase(), + commits: 1, + dates: { + [date]: 1, + }, + }; + } else { + authorData.commits += 1; + authorData.dates[date] = authorData.dates[date] ? authorData.dates[date] + 1 : 1; + } + }); + + return { + total, + byAuthor, + }; +}; + +// prevent babel-plugin-rewire from generating an invalid default during karma tests +export default () => {}; diff --git a/app/assets/javascripts/contributors/stores/index.js b/app/assets/javascripts/contributors/stores/index.js new file mode 100644 index 0000000000..bc739851aa --- /dev/null +++ b/app/assets/javascripts/contributors/stores/index.js @@ -0,0 +1,18 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; +import state from './state'; +import mutations from './mutations'; +import * as getters from './getters'; +import * as actions from './actions'; + +Vue.use(Vuex); + +export const createStore = () => + new Vuex.Store({ + actions, + mutations, + getters, + state: state(), + }); + +export default createStore(); diff --git a/app/assets/javascripts/contributors/stores/mutation_types.js b/app/assets/javascripts/contributors/stores/mutation_types.js new file mode 100644 index 0000000000..62e0a51d5f --- /dev/null +++ b/app/assets/javascripts/contributors/stores/mutation_types.js @@ -0,0 +1,3 @@ +export const SET_CHART_DATA = 'SET_CHART_DATA'; +export const SET_LOADING_STATE = 'SET_LOADING_STATE'; +export const SET_ACTIVE_BRANCH = 'SET_ACTIVE_BRANCH'; diff --git a/app/assets/javascripts/contributors/stores/mutations.js b/app/assets/javascripts/contributors/stores/mutations.js new file mode 100644 index 0000000000..f1f460d072 --- /dev/null +++ b/app/assets/javascripts/contributors/stores/mutations.js @@ -0,0 +1,17 @@ +import * as types from './mutation_types'; + +export default { + [types.SET_LOADING_STATE](state, value) { + state.loading = value; + }, + [types.SET_CHART_DATA](state, chartData) { + Object.assign(state, { + chartData, + }); + }, + [types.SET_ACTIVE_BRANCH](state, branch) { + Object.assign(state, { + branch, + }); + }, +}; diff --git a/app/assets/javascripts/contributors/stores/state.js b/app/assets/javascripts/contributors/stores/state.js new file mode 100644 index 0000000000..1dc1a3c7b7 --- /dev/null +++ b/app/assets/javascripts/contributors/stores/state.js @@ -0,0 +1,5 @@ +export default () => ({ + loading: false, + chartData: null, + branch: 'master', +}); diff --git a/app/assets/javascripts/contributors/utils.js b/app/assets/javascripts/contributors/utils.js new file mode 100644 index 0000000000..7d8932ce49 --- /dev/null +++ b/app/assets/javascripts/contributors/utils.js @@ -0,0 +1,30 @@ +import { getMonthNames } from '~/lib/utils/datetime_utility'; + +/** + * Converts provided string to date and returns formatted value as a year for date in January and month name for the rest + * @param {String} + * @returns {String} - formatted value + * + * xAxisLabelFormatter('01-12-2019') will return '2019' + * xAxisLabelFormatter('02-12-2019') will return 'Feb' + * xAxisLabelFormatter('07-12-2019') will return 'Jul' + */ +export const xAxisLabelFormatter = val => { + const date = new Date(val); + const month = date.getUTCMonth(); + const year = date.getUTCFullYear(); + return month === 0 ? `${year}` : getMonthNames(true)[month]; +}; + +/** + * Formats provided date to YYYY-MM-DD format + * @param {Date} + * @returns {String} - formatted value + */ +export const dateFormatter = date => { + const year = date.getUTCFullYear(); + const month = date.getUTCMonth(); + const day = date.getUTCDate(); + + return `${year}-${`0${month + 1}`.slice(-2)}-${`0${day}`.slice(-2)}`; +}; diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/cluster_form_dropdown.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/cluster_form_dropdown.vue index 3c6da43c4c..e6893c14cd 100644 --- a/app/assets/javascripts/create_cluster/eks_cluster/components/cluster_form_dropdown.vue +++ b/app/assets/javascripts/create_cluster/eks_cluster/components/cluster_form_dropdown.vue @@ -2,14 +2,19 @@ import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue'; import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue'; import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue'; +import { GlIcon } from '@gitlab/ui'; -const findItem = (items, valueProp, value) => items.find(item => item[valueProp] === value); +const toArray = value => [].concat(value); +const itemsProp = (items, prop) => items.map(item => item[prop]); +const defaultSearchFn = (searchQuery, labelProp) => item => + item[labelProp].toLowerCase().indexOf(searchQuery) > -1; export default { components: { DropdownButton, DropdownSearchInput, DropdownHiddenInput, + GlIcon, }, props: { fieldName: { @@ -28,7 +33,7 @@ export default { default: '', }, value: { - type: [Object, String], + type: [Object, Array, String], required: false, default: () => null, }, @@ -72,6 +77,11 @@ export default { required: false, default: false, }, + multiple: { + type: Boolean, + required: false, + default: false, + }, errorMessage: { type: String, required: false, @@ -90,12 +100,11 @@ export default { searchFn: { type: Function, required: false, - default: searchQuery => item => item.name.toLowerCase().indexOf(searchQuery) > -1, + default: defaultSearchFn, }, }, data() { return { - selectedItem: findItem(this.items, this.value), searchQuery: '', }; }, @@ -109,36 +118,52 @@ export default { return this.disabledText; } - if (!this.selectedItem) { + if (!this.selectedItems.length) { return this.placeholder; } - return this.selectedItemLabel; + return this.selectedItemsLabels; }, results() { - if (!this.items) { - return []; - } + return this.getItemsOrEmptyList().filter(this.searchFn(this.searchQuery, this.labelProperty)); + }, + selectedItems() { + const valueProp = this.valueProperty; + const valueList = toArray(this.value); + const items = this.getItemsOrEmptyList(); - return this.items.filter(this.searchFn(this.searchQuery)); + return items.filter(item => valueList.some(value => item[valueProp] === value)); }, - selectedItemLabel() { - return this.selectedItem && this.selectedItem[this.labelProperty]; + selectedItemsLabels() { + return itemsProp(this.selectedItems, this.labelProperty).join(', '); }, - selectedItemValue() { - return (this.selectedItem && this.selectedItem[this.valueProperty]) || ''; - }, - }, - watch: { - value(value) { - this.selectedItem = findItem(this.items, this.valueProperty, value); + selectedItemsValues() { + return itemsProp(this.selectedItems, this.valueProperty).join(', '); }, }, methods: { - select(item) { - this.selectedItem = item; + getItemsOrEmptyList() { + return this.items || []; + }, + selectSingle(item) { this.$emit('input', item[this.valueProperty]); }, + selectMultiple(item) { + const value = toArray(this.value); + const itemValue = item[this.valueProperty]; + const itemValueIndex = value.indexOf(itemValue); + + if (itemValueIndex > -1) { + value.splice(itemValueIndex, 1); + } else { + value.push(itemValue); + } + + this.$emit('input', value); + }, + isSelected(item) { + return this.selectedItems.includes(item); + }, }, }; @@ -146,7 +171,7 @@ export default { diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue index 22ee368b8e..3f7c2204b9 100644 --- a/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue +++ b/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue @@ -1,4 +1,5 @@ diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue index 1188cf0885..57d5f4f541 100644 --- a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue +++ b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue @@ -4,8 +4,8 @@ import { sprintf, s__ } from '~/locale'; import _ from 'underscore'; import { GlFormInput, GlFormCheckbox } from '@gitlab/ui'; import ClusterFormDropdown from './cluster_form_dropdown.vue'; -import RegionDropdown from './region_dropdown.vue'; import { KUBERNETES_VERSIONS } from '../constants'; +import LoadingButton from '~/vue_shared/components/loading_button.vue'; const { mapState: mapRolesState, mapActions: mapRolesActions } = createNamespacedHelpers('roles'); const { mapState: mapRegionsState, mapActions: mapRegionsActions } = createNamespacedHelpers( @@ -22,13 +22,17 @@ const { mapState: mapSecurityGroupsState, mapActions: mapSecurityGroupsActions, } = createNamespacedHelpers('securityGroups'); +const { + mapState: mapInstanceTypesState, + mapActions: mapInstanceTypesActions, +} = createNamespacedHelpers('instanceTypes'); export default { components: { ClusterFormDropdown, - RegionDropdown, GlFormInput, GlFormCheckbox, + LoadingButton, }, props: { gitlabManagedClusterHelpPath: { @@ -39,6 +43,10 @@ export default { type: String, required: true, }, + externalLinkIcon: { + type: String, + required: true, + }, }, computed: { ...mapState([ @@ -51,7 +59,10 @@ export default { 'selectedSubnet', 'selectedRole', 'selectedSecurityGroup', + 'selectedInstanceType', + 'nodeCount', 'gitlabManagedCluster', + 'isCreatingCluster', ]), ...mapRolesState({ roles: 'items', @@ -83,6 +94,11 @@ export default { isLoadingSecurityGroups: 'isLoadingItems', loadingSecurityGroupsError: 'loadingItemsError', }), + ...mapInstanceTypesState({ + instanceTypes: 'items', + isLoadingInstanceTypes: 'isLoadingItems', + loadingInstanceTypesError: 'loadingItemsError', + }), kubernetesVersions() { return KUBERNETES_VERSIONS; }, @@ -98,6 +114,27 @@ export default { securityGroupDropdownDisabled() { return !this.selectedVpc; }, + createClusterButtonDisabled() { + return ( + !this.clusterName || + !this.environmentScope || + !this.kubernetesVersion || + !this.selectedRegion || + !this.selectedKeyPair || + !this.selectedVpc || + !this.selectedSubnet || + !this.selectedRole || + !this.selectedSecurityGroup || + !this.selectedInstanceType || + !this.nodeCount || + this.isCreatingCluster + ); + }, + createClusterButtonLabel() { + return this.isCreatingCluster + ? s__('ClusterIntegration|Creating Kubernetes cluster') + : s__('ClusterIntegration|Create Kubernetes cluster'); + }, kubernetesIntegrationHelpText() { const escapedUrl = _.escape(this.kubernetesIntegrationHelpPath); @@ -115,11 +152,26 @@ export default { roleDropdownHelpText() { return sprintf( s__( - 'ClusterIntegration|Select the IAM Role to allow Amazon EKS and the Kubernetes control plane to manage AWS resources on your behalf. To use a new role name, first create one on %{startLink}Amazon Web Services%{endLink}.', + 'ClusterIntegration|Select the IAM Role to allow Amazon EKS and the Kubernetes control plane to manage AWS resources on your behalf. To use a new role name, first create one on %{startLink}Amazon Web Services %{externalLinkIcon} %{endLink}.', ), { startLink: - '', + '', + externalLinkIcon: this.externalLinkIcon, + endLink: '', + }, + false, + ); + }, + regionsDropdownHelpText() { + return sprintf( + s__( + 'ClusterIntegration|Learn more about %{startLink}Regions %{externalLinkIcon}%{endLink}.', + ), + { + startLink: + '', + externalLinkIcon: this.externalLinkIcon, endLink: '', }, false, @@ -128,11 +180,12 @@ export default { keyPairDropdownHelpText() { return sprintf( s__( - 'ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{startLink}Amazon Web Services%{endLink}.', + 'ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{startLink}Amazon Web Services %{externalLinkIcon} %{endLink}.', ), { startLink: '', + externalLinkIcon: this.externalLinkIcon, endLink: '', }, false, @@ -141,11 +194,12 @@ export default { vpcDropdownHelpText() { return sprintf( s__( - 'ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{startLink}Amazon Web Services%{endLink}.', + 'ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{startLink}Amazon Web Services %{externalLinkIcon} %{endLink}.', ), { startLink: - '', + '', + externalLinkIcon: this.externalLinkIcon, endLink: '', }, false, @@ -154,11 +208,12 @@ export default { subnetDropdownHelpText() { return sprintf( s__( - 'ClusterIntegration|Choose the %{startLink}subnets%{endLink} in your VPC where your worker nodes will run.', + 'ClusterIntegration|Choose the %{startLink}subnets %{externalLinkIcon} %{endLink} in your VPC where your worker nodes will run.', ), { startLink: '', + externalLinkIcon: this.externalLinkIcon, endLink: '', }, false, @@ -167,11 +222,26 @@ export default { securityGroupDropdownHelpText() { return sprintf( s__( - 'ClusterIntegration|Choose the %{startLink}security groups%{endLink} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets.', + 'ClusterIntegration|Choose the %{startLink}security group %{externalLinkIcon} %{endLink} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets.', ), { startLink: '', + externalLinkIcon: this.externalLinkIcon, + endLink: '', + }, + false, + ); + }, + instanceTypesDropdownHelpText() { + return sprintf( + s__( + 'ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}.', + ), + { + startLink: + '', + externalLinkIcon: this.externalLinkIcon, endLink: '', }, false, @@ -195,9 +265,12 @@ export default { mounted() { this.fetchRegions(); this.fetchRoles(); + this.fetchInstanceTypes(); }, methods: { ...mapActions([ + 'createCluster', + 'signOut', 'setClusterName', 'setEnvironmentScope', 'setKubernetesVersion', @@ -207,6 +280,8 @@ export default { 'setRole', 'setKeyPair', 'setSecurityGroup', + 'setInstanceType', + 'setNodeCount', 'setGitlabManagedCluster', ]), ...mapRegionsActions({ fetchRegions: 'fetchItems' }), @@ -215,15 +290,22 @@ export default { ...mapRolesActions({ fetchRoles: 'fetchItems' }), ...mapKeyPairsActions({ fetchKeyPairs: 'fetchItems' }), ...mapSecurityGroupsActions({ fetchSecurityGroups: 'fetchItems' }), + ...mapInstanceTypesActions({ fetchInstanceTypes: 'fetchItems' }), setRegionAndFetchVpcsAndKeyPairs(region) { this.setRegion({ region }); + this.setVpc({ vpc: null }); + this.setKeyPair({ keyPair: null }); + this.setSubnet({ subnet: null }); + this.setSecurityGroup({ securityGroup: null }); this.fetchVpcs({ region }); this.fetchKeyPairs({ region }); }, setVpcAndFetchSubnets(vpc) { this.setVpc({ vpc }); - this.fetchSubnets({ vpc }); - this.fetchSecurityGroups({ vpc }); + this.setSubnet({ subnet: null }); + this.setSecurityGroup({ securityGroup: null }); + this.fetchSubnets({ vpc, region: this.selectedRegion }); + this.fetchSecurityGroups({ vpc, region: this.selectedRegion }); }, }, }; @@ -233,7 +315,12 @@ export default {

    {{ s__('ClusterIntegration|Enter the details for your Amazon EKS Kubernetes cluster') }}

    -

    +
    +
    + +
  • diff --git a/app/assets/javascripts/diffs/components/diff_content.vue b/app/assets/javascripts/diffs/components/diff_content.vue index 9a1e59ec04..a5ffa84e3f 100644 --- a/app/assets/javascripts/diffs/components/diff_content.vue +++ b/app/assets/javascripts/diffs/components/diff_content.vue @@ -124,8 +124,10 @@ export default { :diff-viewer-mode="diffViewerMode" :new-path="diffFile.new_path" :new-sha="diffFile.diff_refs.head_sha" + :new-size="diffFile.new_size" :old-path="diffFile.old_path" :old-sha="diffFile.diff_refs.base_sha" + :old-size="diffFile.old_size" :file-hash="diffFileHash" :project-path="projectPath" :a-mode="diffFile.a_mode" diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue index 2514274224..9236f0d534 100644 --- a/app/assets/javascripts/diffs/components/diff_file.vue +++ b/app/assets/javascripts/diffs/components/diff_file.vue @@ -54,11 +54,12 @@ export default { showLoadingIcon() { return this.isLoadingCollapsedDiff || (!this.file.renderIt && !this.isCollapsed); }, - hasDiffLines() { + hasDiff() { return ( - this.file.highlighted_diff_lines && - this.file.parallel_diff_lines && - this.file.parallel_diff_lines.length > 0 + (this.file.highlighted_diff_lines && + this.file.parallel_diff_lines && + this.file.parallel_diff_lines.length > 0) || + !this.file.blob.readable_text ); }, isFileTooLarge() { @@ -82,7 +83,7 @@ export default { }, watch: { isCollapsed: function fileCollapsedWatch(newVal, oldVal) { - if (!newVal && oldVal && !this.hasDiffLines) { + if (!newVal && oldVal && !this.hasDiff) { this.handleLoadCollapsedDiff(); } @@ -103,7 +104,7 @@ export default { 'setFileCollapsed', ]), handleToggle() { - if (!this.hasDiffLines) { + if (!this.hasDiff) { this.handleLoadCollapsedDiff(); } else { this.isCollapsed = !this.isCollapsed; diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js index 0ff26445a6..62b390a46d 100644 --- a/app/assets/javascripts/dropzone_input.js +++ b/app/assets/javascripts/dropzone_input.js @@ -290,5 +290,5 @@ export default function dropzoneInput(form) { formTextarea.focus(); }); - return Dropzone.forElement($formDropzone.get(0)); + return $formDropzone.get(0) ? Dropzone.forElement($formDropzone.get(0)) : null; } diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue new file mode 100644 index 0000000000..37c9818f86 --- /dev/null +++ b/app/assets/javascripts/error_tracking/components/error_details.vue @@ -0,0 +1,141 @@ + + + diff --git a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue index cd298e2c69..88139ce740 100644 --- a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue +++ b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue @@ -1,11 +1,19 @@ @@ -71,10 +91,17 @@ export default {
    -
    +
    +
    - + @@ -94,13 +128,11 @@ export default {