diff --git a/.codeclimate.yml b/.codeclimate.yml index ecac24b68d..216ecf43be 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -11,11 +11,11 @@ engines: exclude_paths: - "lib/api/v3/*" eslint: - # eslint-plugin-vue is locked to version 2 in codeclimate, we need version 4 - enabled: false + enabled: true + channel: "eslint-4" rubocop: enabled: true - channel: "gitlab-rubocop-0-52" + channel: "gitlab-rubocop-0-52-1" ratings: paths: - Gemfile.lock @@ -45,3 +45,4 @@ exclude_paths: - log/ - backups/ - coverage-javascript/ +- plugins/ diff --git a/.eslintrc b/.eslintrc index ad5eaebcca..8f9cdfb14a 100644 --- a/.eslintrc +++ b/.eslintrc @@ -36,7 +36,7 @@ "import/no-commonjs": "error", "no-multiple-empty-lines": ["error", { "max": 1 }], "promise/catch-or-return": "error", - "no-underscore-dangle": ["error", { "allow": ["__"]}], + "no-underscore-dangle": ["error", { "allow": ["__", "_links"]}], "vue/html-self-closing": ["error", { "html": { "void": "always", diff --git a/.gitignore b/.gitignore index 2004c2a09b..fa39ae01ff 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,4 @@ eslint-report.html /locale/**/LC_MESSAGES /locale/**/*.time_stamp /.rspec +/plugins/* diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9c3556f5cc..5556bf5bc0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.6-golang-1.9-git-2.14-chrome-63.0-node-8.x-yarn-1.2-postgresql-9.6" +image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.6-golang-1.9-git-2.16-chrome-63.0-node-8.x-yarn-1.2-postgresql-9.6" .dedicated-runner: &dedicated-runner retry: 1 @@ -35,8 +35,14 @@ variables: before_script: - bundle --version + - date - source scripts/utils.sh + - date - source scripts/prepare_build.sh + - date + +after_script: + - date stages: - build @@ -88,6 +94,26 @@ stages: - /(^docs[\/-].*|.*-docs$)/ - /(^qa[\/-].*|.*-qa$)/ +# Jobs that only need to pull cache +.dedicated-no-docs-pull-cache-job: &dedicated-no-docs-pull-cache-job + <<: *dedicated-runner + <<: *except-docs-and-qa + <<: *pull-cache + dependencies: + - setup-test-env + stage: test + +# Jobs that do not need a DB +.dedicated-no-docs-no-db-pull-cache-job: &dedicated-no-docs-no-db-pull-cache-job + <<: *dedicated-no-docs-pull-cache-job + variables: + SETUP_DB: "false" + +.rake-exec: &rake-exec + <<: *dedicated-no-docs-no-db-pull-cache-job + script: + - bundle exec rake $CI_JOB_NAME + .rspec-metadata: &rspec-metadata <<: *dedicated-runner <<: *except-docs-and-qa @@ -164,21 +190,23 @@ stages: - master@gitlab/gitlabhq - master@gitlab/gitlab-ee -## -# Trigger a package build in omnibus-gitlab repository -# -package-qa: - <<: *dedicated-runner - image: ruby:2.4-alpine - before_script: [] - stage: build - cache: {} - when: manual +.gitlab-setup: &gitlab-setup + <<: *dedicated-no-docs-pull-cache-job + <<: *use-pg + variables: + CREATE_DB_USER: "true" script: - - scripts/trigger-build-omnibus - only: - - //@gitlab-org/gitlab-ce - - //@gitlab-org/gitlab-ee + # Manually clone gitlab-test and only seed this project in + # db/fixtures/development/04_project.rb thanks to SIZE=1 below + - git clone https://gitlab.com/gitlab-org/gitlab-test.git + /home/git/repositories/gitlab-org/gitlab-test.git + - scripts/gitaly-test-spawn + - force=yes SIZE=1 FIXTURE_PATH="db/fixtures/development" bundle exec rake gitlab:setup + artifacts: + when: on_failure + expire_in: 1d + paths: + - log/development.log # Review docs base .review-docs: &review-docs @@ -201,6 +229,47 @@ package-qa: only: - branches +# DB migration, rollback, and seed jobs +.db-migrate-reset: &db-migrate-reset + <<: *dedicated-no-docs-pull-cache-job + script: + - bundle exec rake db:migrate:reset + +.migration-paths: &migration-paths + <<: *dedicated-no-docs-pull-cache-job + variables: + CREATE_DB_USER: "true" + script: + - git fetch https://gitlab.com/gitlab-org/gitlab-ce.git v9.3.0 + - git checkout -f FETCH_HEAD + - bundle install $BUNDLE_INSTALL_FLAGS + - date + - cp config/gitlab.yml.example config/gitlab.yml + - bundle exec rake db:drop db:create db:schema:load db:seed_fu + - date + - git checkout $CI_COMMIT_SHA + - bundle install $BUNDLE_INSTALL_FLAGS + - date + - . scripts/prepare_build.sh + - date + - bundle exec rake db:migrate + +## +# Trigger a package build in omnibus-gitlab repository +# +package-qa: + <<: *dedicated-runner + image: ruby:2.4-alpine + before_script: [] + stage: build + cache: {} + when: manual + script: + - scripts/trigger-build-omnibus + only: + - //@gitlab-org/gitlab-ce + - //@gitlab-org/gitlab-ee + # Trigger a docs build in gitlab-docs # Useful to preview the docs changes live review-docs-deploy: @@ -265,7 +334,7 @@ update-tests-metadata: flaky-examples-check: <<: *dedicated-runner - image: ruby:2.3-alpine + image: ruby:2.4-alpine services: [] before_script: [] variables: @@ -299,7 +368,9 @@ compile-assets: <<: *default-cache script: - node --version + - date - yarn install --frozen-lockfile --cache-folder .yarn-cache + - date - bundle exec rake gitlab:assets:compile artifacts: expire_in: 7d @@ -323,90 +394,75 @@ setup-test-env: - tmp/tests - config/secrets.yml -rspec-pg 0 27: *rspec-metadata-pg -rspec-pg 1 27: *rspec-metadata-pg -rspec-pg 2 27: *rspec-metadata-pg -rspec-pg 3 27: *rspec-metadata-pg -rspec-pg 4 27: *rspec-metadata-pg -rspec-pg 5 27: *rspec-metadata-pg -rspec-pg 6 27: *rspec-metadata-pg -rspec-pg 7 27: *rspec-metadata-pg -rspec-pg 8 27: *rspec-metadata-pg -rspec-pg 9 27: *rspec-metadata-pg -rspec-pg 10 27: *rspec-metadata-pg -rspec-pg 11 27: *rspec-metadata-pg -rspec-pg 12 27: *rspec-metadata-pg -rspec-pg 13 27: *rspec-metadata-pg -rspec-pg 14 27: *rspec-metadata-pg -rspec-pg 15 27: *rspec-metadata-pg -rspec-pg 16 27: *rspec-metadata-pg -rspec-pg 17 27: *rspec-metadata-pg -rspec-pg 18 27: *rspec-metadata-pg -rspec-pg 19 27: *rspec-metadata-pg -rspec-pg 20 27: *rspec-metadata-pg -rspec-pg 21 27: *rspec-metadata-pg -rspec-pg 22 27: *rspec-metadata-pg -rspec-pg 23 27: *rspec-metadata-pg -rspec-pg 24 27: *rspec-metadata-pg -rspec-pg 25 27: *rspec-metadata-pg -rspec-pg 26 27: *rspec-metadata-pg +rspec-pg 0 28: *rspec-metadata-pg +rspec-pg 1 28: *rspec-metadata-pg +rspec-pg 2 28: *rspec-metadata-pg +rspec-pg 3 28: *rspec-metadata-pg +rspec-pg 4 28: *rspec-metadata-pg +rspec-pg 5 28: *rspec-metadata-pg +rspec-pg 6 28: *rspec-metadata-pg +rspec-pg 7 28: *rspec-metadata-pg +rspec-pg 8 28: *rspec-metadata-pg +rspec-pg 9 28: *rspec-metadata-pg +rspec-pg 10 28: *rspec-metadata-pg +rspec-pg 11 28: *rspec-metadata-pg +rspec-pg 12 28: *rspec-metadata-pg +rspec-pg 13 28: *rspec-metadata-pg +rspec-pg 14 28: *rspec-metadata-pg +rspec-pg 15 28: *rspec-metadata-pg +rspec-pg 16 28: *rspec-metadata-pg +rspec-pg 17 28: *rspec-metadata-pg +rspec-pg 18 28: *rspec-metadata-pg +rspec-pg 19 28: *rspec-metadata-pg +rspec-pg 20 28: *rspec-metadata-pg +rspec-pg 21 28: *rspec-metadata-pg +rspec-pg 22 28: *rspec-metadata-pg +rspec-pg 23 28: *rspec-metadata-pg +rspec-pg 24 28: *rspec-metadata-pg +rspec-pg 25 28: *rspec-metadata-pg +rspec-pg 26 28: *rspec-metadata-pg +rspec-pg 27 28: *rspec-metadata-pg -rspec-mysql 0 27: *rspec-metadata-mysql -rspec-mysql 1 27: *rspec-metadata-mysql -rspec-mysql 2 27: *rspec-metadata-mysql -rspec-mysql 3 27: *rspec-metadata-mysql -rspec-mysql 4 27: *rspec-metadata-mysql -rspec-mysql 5 27: *rspec-metadata-mysql -rspec-mysql 6 27: *rspec-metadata-mysql -rspec-mysql 7 27: *rspec-metadata-mysql -rspec-mysql 8 27: *rspec-metadata-mysql -rspec-mysql 9 27: *rspec-metadata-mysql -rspec-mysql 10 27: *rspec-metadata-mysql -rspec-mysql 11 27: *rspec-metadata-mysql -rspec-mysql 12 27: *rspec-metadata-mysql -rspec-mysql 13 27: *rspec-metadata-mysql -rspec-mysql 14 27: *rspec-metadata-mysql -rspec-mysql 15 27: *rspec-metadata-mysql -rspec-mysql 16 27: *rspec-metadata-mysql -rspec-mysql 17 27: *rspec-metadata-mysql -rspec-mysql 18 27: *rspec-metadata-mysql -rspec-mysql 19 27: *rspec-metadata-mysql -rspec-mysql 20 27: *rspec-metadata-mysql -rspec-mysql 21 27: *rspec-metadata-mysql -rspec-mysql 22 27: *rspec-metadata-mysql -rspec-mysql 23 27: *rspec-metadata-mysql -rspec-mysql 24 27: *rspec-metadata-mysql -rspec-mysql 25 27: *rspec-metadata-mysql -rspec-mysql 26 27: *rspec-metadata-mysql +rspec-mysql 0 28: *rspec-metadata-mysql +rspec-mysql 1 28: *rspec-metadata-mysql +rspec-mysql 2 28: *rspec-metadata-mysql +rspec-mysql 3 28: *rspec-metadata-mysql +rspec-mysql 4 28: *rspec-metadata-mysql +rspec-mysql 5 28: *rspec-metadata-mysql +rspec-mysql 6 28: *rspec-metadata-mysql +rspec-mysql 7 28: *rspec-metadata-mysql +rspec-mysql 8 28: *rspec-metadata-mysql +rspec-mysql 9 28: *rspec-metadata-mysql +rspec-mysql 10 28: *rspec-metadata-mysql +rspec-mysql 11 28: *rspec-metadata-mysql +rspec-mysql 12 28: *rspec-metadata-mysql +rspec-mysql 13 28: *rspec-metadata-mysql +rspec-mysql 14 28: *rspec-metadata-mysql +rspec-mysql 15 28: *rspec-metadata-mysql +rspec-mysql 16 28: *rspec-metadata-mysql +rspec-mysql 17 28: *rspec-metadata-mysql +rspec-mysql 18 28: *rspec-metadata-mysql +rspec-mysql 19 28: *rspec-metadata-mysql +rspec-mysql 20 28: *rspec-metadata-mysql +rspec-mysql 21 28: *rspec-metadata-mysql +rspec-mysql 22 28: *rspec-metadata-mysql +rspec-mysql 23 28: *rspec-metadata-mysql +rspec-mysql 24 28: *rspec-metadata-mysql +rspec-mysql 25 28: *rspec-metadata-mysql +rspec-mysql 26 28: *rspec-metadata-mysql +rspec-mysql 27 28: *rspec-metadata-mysql -spinach-pg 0 3: *spinach-metadata-pg -spinach-pg 1 3: *spinach-metadata-pg -spinach-pg 2 3: *spinach-metadata-pg +spinach-pg 0 2: *spinach-metadata-pg +spinach-pg 1 2: *spinach-metadata-pg -spinach-mysql 0 3: *spinach-metadata-mysql -spinach-mysql 1 3: *spinach-metadata-mysql -spinach-mysql 2 3: *spinach-metadata-mysql - -# Static analysis jobs -.ruby-static-analysis: &ruby-static-analysis - variables: - SIMPLECOV: "false" - SETUP_DB: "false" - -.rake-exec: &rake-exec - <<: *dedicated-runner - <<: *except-docs-and-qa - <<: *pull-cache - <<: *ruby-static-analysis - stage: test - script: - - bundle exec rake $CI_JOB_NAME +spinach-mysql 0 2: *spinach-metadata-mysql +spinach-mysql 1 2: *spinach-metadata-mysql static-analysis: - <<: *dedicated-runner - <<: *except-docs - <<: *ruby-static-analysis - stage: test + <<: *dedicated-no-docs-no-db-pull-cache-job + dependencies: + - compile-assets + - setup-test-env script: - scripts/static-analysis cache: @@ -463,15 +519,6 @@ ee_compat_check: paths: - ee_compat_check/patches/*.patch -# DB migration, rollback, and seed jobs -.db-migrate-reset: &db-migrate-reset - <<: *dedicated-runner - <<: *except-docs-and-qa - <<: *pull-cache - stage: test - script: - - bundle exec rake db:migrate:reset - db:migrate:reset-pg: <<: *db-migrate-reset <<: *use-pg @@ -486,25 +533,6 @@ db:check-schema-pg: script: - source scripts/schema_changed.sh -.migration-paths: &migration-paths - <<: *dedicated-runner - <<: *except-docs-and-qa - <<: *pull-cache - stage: test - variables: - SETUP_DB: "false" - CREATE_DB_USER: "true" - script: - - git fetch https://gitlab.com/gitlab-org/gitlab-ce.git v9.3.0 - - git checkout -f FETCH_HEAD - - bundle install $BUNDLE_INSTALL_FLAGS - - cp config/gitlab.yml.example config/gitlab.yml - - bundle exec rake db:drop db:create db:schema:load db:seed_fu - - git checkout $CI_COMMIT_SHA - - bundle install $BUNDLE_INSTALL_FLAGS - - . scripts/prepare_build.sh - - bundle exec rake db:migrate - migration:path-pg: <<: *migration-paths <<: *use-pg @@ -514,10 +542,7 @@ migration:path-mysql: <<: *use-mysql .db-rollback: &db-rollback - <<: *dedicated-runner - <<: *except-docs-and-qa - <<: *pull-cache - stage: test + <<: *dedicated-no-docs-pull-cache-job script: - bundle exec rake db:rollback STEP=119 - bundle exec rake db:migrate @@ -530,27 +555,6 @@ db:rollback-mysql: <<: *db-rollback <<: *use-mysql -.gitlab-setup: &gitlab-setup - <<: *dedicated-runner - <<: *except-docs-and-qa - <<: *pull-cache - stage: test - variables: - SIZE: "1" - SETUP_DB: "false" - CREATE_DB_USER: "true" - FIXTURE_PATH: db/fixtures/development - script: - - git clone https://gitlab.com/gitlab-org/gitlab-test.git - /home/git/repositories/gitlab-org/gitlab-test.git - - scripts/gitaly-test-spawn - - force=yes bundle exec rake gitlab:setup - artifacts: - when: on_failure - expire_in: 1d - paths: - - log/development.log - gitlab:setup-pg: <<: *gitlab-setup <<: *use-pg @@ -561,10 +565,7 @@ gitlab:setup-mysql: # Frontend-related jobs gitlab:assets:compile: - <<: *dedicated-runner - <<: *except-docs-and-qa - <<: *pull-cache - stage: test + <<: *dedicated-no-docs-no-db-pull-cache-job dependencies: [] variables: NODE_ENV: "production" @@ -574,7 +575,9 @@ gitlab:assets:compile: WEBPACK_REPORT: "true" NO_COMPRESSION: "true" script: + - date - yarn install --frozen-lockfile --production --cache-folder .yarn-cache + - date - bundle exec rake gitlab:assets:compile artifacts: name: webpack-report @@ -583,17 +586,16 @@ gitlab:assets:compile: - webpack-report/ karma: - <<: *dedicated-runner - <<: *except-docs-and-qa - <<: *pull-cache + <<: *dedicated-no-docs-pull-cache-job <<: *use-pg - stage: test - variables: - BABEL_ENV: "coverage" - CHROME_LOG_FILE: "chrome_debug.log" + dependencies: + - compile-assets + - setup-test-env script: + - export BABEL_ENV=coverage CHROME_LOG_FILE=chrome_debug.log + - date - scripts/gitaly-test-spawn - - bundle exec rake gettext:po_to_json + - date - bundle exec rake karma coverage: '/^Statements *: (\d+\.\d+%)/' artifacts: @@ -601,28 +603,29 @@ karma: expire_in: 31d when: always paths: - - chrome_debug.log - - coverage-javascript/ + - chrome_debug.log + - coverage-javascript/ codequality: - <<: *except-docs - <<: *pull-cache - before_script: [] + <<: *dedicated-no-docs-no-db-pull-cache-job image: docker:latest - stage: test - variables: - SETUP_DB: "false" - DOCKER_DRIVER: overlay + before_script: [] services: - docker:dind + variables: + SETUP_DB: "false" + DOCKER_DRIVER: overlay2 + CODECLIMATE_FORMAT: json + cache: {} + dependencies: [] script: - - cp .rubocop.yml .rubocop.yml.bak - - grep -v "rubocop-gitlab-security" .rubocop.yml.bak > .rubocop.yml - - docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc dev.gitlab.org:5005/gitlab/gitlab-build-images:gitlab-codeclimate-v2 analyze -f json > raw_codeclimate.json - - cat raw_codeclimate.json | docker run -i stedolan/jq -c 'map({check_name,fingerprint,location})' > codeclimate.json - - mv .rubocop.yml.bak .rubocop.yml + - apk update && apk add jq + - ./scripts/codequality analyze -f json > raw_codeclimate.json || true + # The following line keeps only the fields used in the MR widget, reducing the JSON artifact size + - jq -c 'map({check_name,description,fingerprint,location})' raw_codeclimate.json > codeclimate.json artifacts: paths: [codeclimate.json] + expire_in: 1 week sast: <<: *except-docs @@ -636,11 +639,7 @@ sast: paths: [gl-sast-report.json] qa:internal: - <<: *dedicated-runner - <<: *except-docs - stage: test - variables: - SETUP_DB: "false" + <<: *dedicated-no-docs-no-db-pull-cache-job services: [] script: - cd qa/ @@ -648,11 +647,7 @@ qa:internal: - bundle exec rspec qa:selectors: - <<: *dedicated-runner - <<: *except-docs - stage: test - variables: - SETUP_DB: "false" + <<: *dedicated-no-docs-no-db-pull-cache-job services: [] script: - cd qa/ @@ -660,14 +655,8 @@ qa:selectors: - bundle exec bin/qa Test::Sanity::Selectors coverage: - <<: *dedicated-runner - <<: *except-docs-and-qa - <<: *pull-cache + <<: *dedicated-no-docs-no-db-pull-cache-job stage: post-test - services: [] - variables: - SETUP_DB: "false" - USE_BUNDLE_INSTALL: "true" script: - bundle exec scripts/merge-simplecov coverage: '/LOC \((\d+\.\d+%)\) covered.$/' @@ -679,26 +668,25 @@ coverage: - coverage/assets/ lint:javascript:report: - <<: *dedicated-runner - <<: *except-docs-and-qa - <<: *pull-cache + <<: *dedicated-no-docs-no-db-pull-cache-job stage: post-test dependencies: - compile-assets - setup-test-env before_script: [] script: + - date - find app/ spec/ -name '*.js' -exec sed --in-place 's|/\* eslint-disable .*\*/||' {} \; # run report over all files + - date - yarn run eslint-report || true # ignore exit code artifacts: name: eslint-report expire_in: 31d paths: - - eslint-report.html + - eslint-report.html pages: - <<: *dedicated-runner - <<: *pull-cache + <<: *dedicated-no-docs-no-db-pull-cache-job before_script: [] stage: pages dependencies: @@ -723,10 +711,7 @@ pages: # Insurance in case a gem needed by one of our releases gets yanked from # rubygems.org in the future. cache gems: - <<: *dedicated-runner - <<: *pull-cache - variables: - SETUP_DB: "false" + <<: *dedicated-no-docs-no-db-pull-cache-job script: - bundle package --all --all-platforms artifacts: diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md index aec734870d..3e58d2a867 100644 --- a/.gitlab/issue_templates/Bug.md +++ b/.gitlab/issue_templates/Bug.md @@ -1,3 +1,4 @@ + ### Summary diff --git a/.rubocop.yml b/.rubocop.yml index 8a9a1e3275..90dac88453 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -10,15 +10,27 @@ AllCops: Exclude: - 'vendor/**/*' - 'node_modules/**/*' - - 'db/*' + - 'db/**/*' - 'db/fixtures/**/*' - - 'db/geo/*' + - 'ee/db/**/*' - 'tmp/**/*' - 'bin/**/*' - 'generator_templates/**/*' - 'builds/**/*' + - 'plugins/**/*' CacheRootDirectory: tmp +# This cop checks whether some constant value isn't a +# mutable literal (e.g. array or hash). +Style/MutableConstant: + Enabled: true + Exclude: + - 'db/migrate/**/*' + - 'db/post_migrate/**/*' + - 'ee/db/migrate/**/*' + - 'ee/db/post_migrate/**/*' + - 'ee/db/geo/migrate/**/*' + # Gitlab ################################################################### Gitlab/ModuleWithInstanceVariables: @@ -36,3 +48,16 @@ Gitlab/ModuleWithInstanceVariables: Gitlab/HTTParty: Enabled: true + +GitlabSecurity/PublicSend: + Enabled: true + Exclude: + - 'config/**/*' + - 'db/**/*' + - 'features/**/*' + - 'lib/**/*.rake' + - 'qa/**/*' + - 'spec/**/*' + - 'ee/db/**/*' + - 'ee/lib/**/*.rake' + - 'ee/spec/**/*' diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 7a12c8473f..d443238b9e 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -124,8 +124,8 @@ Lint/DuplicateMethods: - 'lib/gitlab/git/repository.rb' - 'lib/gitlab/git/tree.rb' - 'lib/gitlab/git/wiki_page.rb' - - 'lib/gitlab/ldap/person.rb' - - 'lib/gitlab/o_auth/user.rb' + - 'lib/gitlab/auth/ldap/person.rb' + - 'lib/gitlab/auth/o_auth/user.rb' # Offense count: 4 Lint/InterpolationCheck: @@ -812,7 +812,7 @@ Style/TrivialAccessors: Exclude: - 'app/models/external_issue.rb' - 'app/serializers/base_serializer.rb' - - 'lib/gitlab/ldap/person.rb' + - 'lib/gitlab/auth/ldap/person.rb' - 'lib/system_check/base_check.rb' # Offense count: 4 diff --git a/CHANGELOG.md b/CHANGELOG.md index ee1e4c3e8a..0c1c3a572f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,47 +2,188 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. -## 10.5.6 (2018-03-16) +## 10.6.0 (2018-03-22) -### Security (2 changes) +### Security (4 changes) - Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337 +- Ensure that OTP backup codes are always invalidated. +- Add verification for GitLab Pages custom domains. - Fix GitLab Auth0 integration signing in the wrong user. +### Fixed (75 changes, 17 of them are from the community) -## 10.5.5 (2018-03-15) - -### Fixed (3 changes) - -- Fix missing uploads after group transfer. !17658 -- Fix code and wiki search results when filename is non-ASCII. -- Remove double caching of Repository#empty?. - -### Performance (2 changes) - -- Adding missing indexes on taggings table. -- Add index on section_name_id on ci_build_trace_sections table. - - -## 10.5.4 (2018-03-08) - -### Fixed (11 changes) - +- Ensure users cannot create environments with leading or trailing slashes (Fixes #39885). !15273 +- Fix new project path input overlapping. !16755 (George Tsiolis) +- Respect description and visibility when creating project from template. !16820 (George Tsiolis) +- Remove user notification settings for groups and projects when user leaves. !16906 (Jacopo Beschi @jacopo-beschi) +- Fix Teleporting Emoji. !16963 (Jared Deckard ) +- Fix duplicate system notes when merging a merge request. !17035 +- Fix breadcrumb on labels page for groups. !17045 (Onuwa Nnachi Isaac) +- Fix user avatar's vertical align on the issues and merge requests pages. !17072 (Laszlo Karpati) +- Fix settings panels not expanding when fragment hash linked. !17074 +- Fix 404 when listing archived projects in a group where all projects have been archived. !17077 (Ashley Dumaine) +- Allow to call PUT /projects/:id API with only ci_config_path specified. !17105 (Laszlo Karpati) +- Fix long list of recipients on group request membership email. !17121 (Jacopo Beschi @jacopo-beschi) +- Remove duplicated error message on duplicate variable validation. !17135 +- Keep "Import project" tab/form active when validation fails trying to import "Repo by URL". !17136 +- Fixed bug with unauthenticated requests through git ssh. !17149 +- Allows project rename after validation error. !17150 +- Fix "Remove source branch" button in Merge request widget during merge when pipeline succeeds state. !17192 +- Add missing pagination on the commit diff endpoint. !17203 (Maxime Roussin-Bélanger) +- Fix get a single pages domain when project path contains a period. !17206 (Travis Miller) +- remove avater underline. !17219 (Ken Ding) +- Allows the usage of /milestone quick action for group milestones. !17239 (Jacopo Beschi @jacopo-beschi) - Encode branch name as binary before creating a RPC request to copy attributes. !17291 - Restart Unicorn and Sidekiq when GRPC throws 14:Endpoint read failed. !17293 +- Do not persist Google Project verification flash errors after a page reload. !17299 - Ensure group issues and merge requests pages show results from subgroups when there are no results from the current group. !17312 - Prevent trace artifact migration to incur data loss. !17313 +- Fixes gpg popover layout. !17323 - Return a 404 instead of 403 if the repository does not exist on disk. !17341 +- Fix Slack/Mattermost notifications not respecting `notify_only_default_branch` setting for pushes. !17345 +- Fix Group labels load failure when there are duplicate labels present. !17353 - Allow Prometheus application to be installed from Cluster applications. !17372 - Fixes Prometheus admin configuration page. !17377 +- Enable filtering MR list based on clicked label in MR sidebar. !17390 - Fix code and wiki search results pages when non-ASCII text is displayed. !17413 +- Count comments on diffs and discussions as contributions for the contributions calendar. !17418 (Riccardo Padovani) +- Add Assignees vue component missing data container. !17426 (George Tsiolis) +- Update tooltip on pipeline cancel to Stop (#42946). !17444 +- Removing the two factor check when the user sets a new password. !17457 +- Fix quick actions for users who cannot update issues and merge requests. !17482 +- Stop loading spinner on error of milestone update on issue. !17507 (Takuya Noguchi) +- Set margins around dropdown dividers to 4px. !17517 - Fix pages flaky failure by reloading stale object. !17522 -- Fixed issue edit shortcut not opening edit form. +- Remove extra breadcrumb on tags. !17562 (Takuya Noguchi) +- Fix missing uploads after group transfer. !17658 +- Fix markdown table showing extra column. !17669 +- Ensure the API returns https links when https is configured. !17681 +- Sanitize extra blank spaces used when uploading a SSH key. !40552 +- Render htmlentities correctly for links not supported by Rinku. +- Keep link when redacting unauthorized object links. +- Handle empty state in Pipelines page. - Revert Project.public_or_visible_to_user changes and only apply to snippets. +- Release libgit2 cache and open file descriptors after `git gc` run. +- Fix project dashboard showing the wrong timestamps. +- Fix "Can't modify frozen hash" error when project is destroyed. +- Fix Error 500 when viewing a commit with a GPG signature in Geo. +- Don't error out in system hook if user has `nil` datetime columns. +- Remove double caching of Repository#empty?. +- Don't delete todos or unassign issues and MRs when a user leaves a project. +- Don't cache a nil repository root ref to prevent caching issues. +- Escape HTML entities in commit messages. +- Verify project import status again before marking as failed. +- [GitHub Import] Create an empty wiki if wiki import failed. +- Create empty wiki when import from GitLab and wiki is not there. +- Make sure wiki exists when it's enabled. +- Fix broken loading state for close issue button. +- Fix code and wiki search results when filename is non-ASCII. +- Fix file upload on project show page. +- Fix squashing when a file is renamed. +- Show loading button inline in refresh button in MR widget. +- Fix close button on issues not working on mobile. +- Adds tooltip in environment names to increase readability. +- Fixed issue edit shortcut not opening edit form. +- Fix 500 error being shown when diff has context marker with invalid encoding. +- Render modified icon for moved file in changes dropdown. +- Remember assignee when moving an issue. -### Performance (1 change) +### Changed (16 changes, 9 of them are from the community) +- Allow including custom attributes in API responses. !16526 (Markus Koller) +- Apply new default and inline label design. !16956 (George Tsiolis) +- Remove whitespace from the username/email sign in form field. !17020 (Peter lauck) +- CI charts now include the current day. !17032 (Dakkaron) +- Hide CI secret variable values after saving. !17044 +- Add new modal Vue component. !17108 +- Asciidoc now support inter-document cross references between files in repository. !17125 (Turo Soisenniemi) +- Update issue closing pattern to allow variations in punctuation. !17198 (Vicky Chijwani) +- Add a button to deploy a runner to a Kubernetes cluster in the settings page. !17278 +- Pages custom domain: allow update of key/certificate. !17376 (rfwatson) +- Clear the Labels dropdown search filter after a selection is made. !17393 (Andrew Torres) +- Hook data for pipelines includes detailed_status. !17607 +- Avoid showing unnecessary Trigger checkboxes for project Integrations with only one event. !17607 +- Display a link to external issue tracker when enabled. +- Allow token authentication on go-get request. +- Update SSH key link to include existing keys. (Brendan O'Leary) + +### Performance (24 changes, 5 of them are from the community) + +- Add catch-up background migration to migrate pipeline stages. !15741 +- Move BoardNewIssue vue component. !16947 (George Tsiolis) +- Move IssuableTimeTracker vue component. !16948 (George Tsiolis) +- Move RecentSearchesDropdownContent vue component. !16951 (George Tsiolis) +- Move Assignees vue component. !16952 (George Tsiolis) +- Improve performance of pipeline page by reducing DB queries. !17168 +- Store sha256 checksum to job artifacts. !17354 +- Move SidebarAssignees vue component. !17398 (George Tsiolis) +- Improve database response time for user activity listing. !17454 +- Use persisted/memoized value for MRs shas instead of doing git lookups. !17555 +- Cache MergeRequests can_be_resolved_in_ui? git operations. !17589 +- Prevent the graphs page from generating unnecessary Gitaly requests. !37602 +- Use a user object in ApplicationHelper#avatar_icon where possible to avoid N+1 queries. !42800 +- Submit a single batch blob RPC to Gitaly per HTTP request when viewing diffs. +- Avoid re-fetching merge-base SHA from Gitaly unnecessarily. - Don't use ProjectsFinder in TodosFinder. +- Adding missing indexes on taggings table. +- Add index on section_name_id on ci_build_trace_sections table. +- Cache column_exists? for application settings. +- Cache table_exists?('application_settings') to reduce repeated schema reloads. +- Make --prune a configurable parameter in fetching a git remote. +- Fix timeouts loading /admin/projects page. +- Add partial indexes on todos to handle users with many todos. +- Optimize search queries on the search page by setting a limit for matching records in project scope. + +### Added (30 changes, 9 of them are from the community) + +- Add CommonMark markdown engine (experimental). !14835 (blackst0ne) +- API: Get references a commit is pushed to. !15026 (Robert Schilling) +- Add overview of branches and a filter for active/stale branches. !15402 (Takuya Noguchi) +- Add project export API. !15860 (Travis Miller) +- expose more metrics in merge requests api. !16589 (haseebeqx) +- #28481: Display time tracking totals on milestone page. !16753 (Riccardo Padovani) +- Add a button on the project page to set up a Kubernetes cluster and enable Auto DevOps. !16900 +- Include cycle time in usage ping data. !16973 +- Add ability to use external plugins as an alternative to system hooks. !17003 +- Add search param to Branches API. !17005 (bunufi) +- API endpoint for importing a project export. !17025 +- Display ingress IP address in the Kubernetes page. !17052 +- Implemented badge API endpoints. !17082 +- Allow installation of GitLab Runner with a single click. !17134 +- Allow commits endpoint to work over all commits of a repository. !17182 +- Display Runner IP Address. !17286 +- Add archive feature to trace. !17314 +- Allow maintainers to push to forks of their projects when a merge request is open. !17395 +- Foreground verification of uploads and LFS objects. !17402 +- Adds updated_at filter to issues and merge_requests API. !17417 (Jacopo Beschi @jacopo-beschi) +- Port /wip quick action command to Merge Request creation (on description). !17463 (Adam Pahlevi) +- Add a paragraph about security implications on Cluster's page. !17486 +- Add plugins list to the system hooks page. !17518 +- Enable privileged mode for GitLab Runner. !17528 +- Expose GITLAB_FEATURES as CI/CD variable (fixes #40994). +- Upgrade GitLab Workhorse to 4.0.0. +- Allow CI/CD Jobs being grouped on version strings. +- Add discussions API for Issues and Snippets. +- Add one group board to Libre. +- Add support for filtering by source and target branch to merge requests API. + +### Other (14 changes, 3 of them are from the community) + +- Update vue component naming guidelines. !17018 (George Tsiolis) +- Added new design for promotion modals. !17197 +- Update to github-linguist 5.3.x. !17241 (Ken Ding) +- update toml-rb to 1.0.0. !17259 (Ken Ding) +- Keep track of projects a user interacted with. !17327 +- Enables eslint in codeclimate job. !17392 +- Port Labels Select dropdown to Vue. !17411 +- Add NOT NULL constraint to projects.namespace_id. !17448 +- Ensure foreign keys on clusters applications. !17488 +- Started translation into Turkish, Indonesian and Filipino. !17526 +- Add documentation for displayed K8s Ingress IP address (#44330). !17836 +- Move Ruby endpoints to OPT_OUT. +- Upgrade Workhorse to version 3.8.0 to support structured logging. +- Use host URL to build JIRA remote link icon. ## 10.5.3 (2018-03-01) @@ -269,6 +410,32 @@ entry. - Adds empty state illustration for pending job. +## 10.4.5 (2018-03-01) + +### Security (1 change) + +- Ensure that OTP backup codes are always invalidated. + + +## 10.4.4 (2018-02-16) + +### Security (1 change) + +- Update nokogiri to 1.8.2. !16807 + +### Fixed (9 changes) + +- Fix 500 error when loading a merge request with an invalid comment. !16795 +- Cleanup new branch/merge request form in issues. !16854 +- Fix GitLab import leaving group_id on ProjectLabel. !16877 +- Fix forking projects when no restricted visibility levels are defined applicationwide. !16881 +- Resolve PrepareUntrackedUploads PostgreSQL syntax error. !17019 +- Fixed error 500 when removing an identity with synced attributes and visiting the profile page. !17054 +- Validate user namespace before saving so that errors persist on model. +- LDAP Person no longer throws exception on invalid entry. +- Fix JIRA not working when a trailing slash is included. + + ## 10.4.3 (2018-02-05) ### Security (4 changes) @@ -474,6 +641,13 @@ entry. - Use a background migration for issues.closed_at. +## 10.3.8 (2018-03-01) + +### Security (1 change) + +- Ensure that OTP backup codes are always invalidated. + + ## 10.3.7 (2018-02-05) ### Security (4 changes) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ed56da0353..76ee6265c5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -174,7 +174,7 @@ Assigning a team label makes sure issues get the attention of the appropriate people. The current team labels are ~Build, ~"CI/CD", ~Discussion, ~Documentation, ~Edge, -~Geo, ~Gitaly, ~Platform, ~Monitoring, ~Release, and ~"UX". +~Geo, ~Gitaly, ~Monitoring, ~Platform, ~Release, ~"Security Products" and ~"UX". The descriptions on the [labels page][labels-page] explain what falls under the responsibility of each team. @@ -196,6 +196,17 @@ release. There are two levels of priority labels: milestone. If these issues are not done in the current release, they will strongly be considered for the next release. +### Severity labels (~S1, ~S2, etc.) + +Severity labels help us clearly communicate the impact of a ~bug on users. + +| Label | Meaning | Example | +|-------|------------------------------------------|---------| +| ~S1 | Feature broken, no workaround | Unable to create an issue | +| ~S2 | Feature broken, workaround unacceptable | Can push commits, but only via the command line | +| ~S3 | Feature broken, workaround acceptable | Can create merge requests only from the Merge Requests page, not through the Issue | +| ~S4 | Cosmetic issue | Label colors are incorrect / not being displayed | + ### Label for community contributors (~"Accepting Merge Requests") Issues that are beneficial to our users, 'nice to haves', that we currently do @@ -397,9 +408,9 @@ For issues related to the open source stewardship of GitLab, there is the ~"stewardship" label. This label is to be used for issues in which the stewardship of GitLab -is a topic of discussion. For instance if GitLab Inc. is planning to remove -features from GitLab CE to make exclusive in GitLab EE, related issues -would be labelled with ~"stewardship". +is a topic of discussion. For instance if GitLab Inc. is planning to add +features from GitLab EE to GitLab CE, related issues would be labelled with +~"stewardship". A recent example of this was the issue for [bringing the time tracking API to GitLab CE][time-tracking-issue]. diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 9a55e28031..8f63f4f9a1 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -0.81.0 +0.91.0 diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION index ee6cdce3c2..39e898a4f9 100644 --- a/GITLAB_PAGES_VERSION +++ b/GITLAB_PAGES_VERSION @@ -1 +1 @@ -0.6.1 +0.7.1 diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION index 090ea9dad1..1aa5e414fd 100644 --- a/GITLAB_SHELL_VERSION +++ b/GITLAB_SHELL_VERSION @@ -1 +1 @@ -6.0.3 +6.0.4 diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index 40c341bdcd..fcdb2e109f 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -3.6.0 +4.0.0 diff --git a/Gemfile b/Gemfile index 97d40857e1..bc30c31c38 100644 --- a/Gemfile +++ b/Gemfile @@ -81,7 +81,7 @@ gem 'gollum-lib', '~> 4.2', require: false gem 'gollum-rugged_adapter', '~> 0.4.4', require: false # Language detection -gem 'github-linguist', '~> 4.7.0', require: 'linguist' +gem 'github-linguist', '~> 5.3.3', require: 'linguist' # API gem 'grape', '~> 1.0' @@ -126,6 +126,7 @@ gem 'html-pipeline', '~> 1.11.0' gem 'deckar01-task_list', '2.0.0' gem 'gitlab-markup', '~> 1.6.2' gem 'redcarpet', '~> 3.4' +gem 'commonmarker', '~> 0.17' gem 'RedCloth', '~> 4.3.2' gem 'rdoc', '~> 4.2' gem 'org-ruby', '~> 0.9.12' @@ -401,6 +402,7 @@ gem 'sys-filesystem', '~> 1.1.6' # SSH host key support gem 'net-ssh', '~> 4.1.0' +gem 'sshkey', '~> 1.9.0' # Required for ED25519 SSH host key support group :ed25519 do @@ -410,11 +412,13 @@ group :ed25519 do end # Gitaly GRPC client -gem 'gitaly-proto', '~> 0.84.0', require: 'gitaly' +gem 'gitaly-proto', '~> 0.88.0', require: 'gitaly' +gem 'grpc', '~> 1.10.0' + # Locked until https://github.com/google/protobuf/issues/4210 is closed gem 'google-protobuf', '= 3.5.1' -gem 'toml-rb', '~> 0.3.15', require: false +gem 'toml-rb', '~> 1.0.0', require: false # Feature toggles gem 'flipper', '~> 0.11.0' diff --git a/Gemfile.lock b/Gemfile.lock index 4022e28961..8957f1f386 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -131,6 +131,8 @@ GEM coercible (1.0.0) descendants_tracker (~> 0.0.1) colorize (0.7.7) + commonmarker (0.17.8) + ruby-enum (~> 0.5) concord (0.1.5) adamantium (~> 0.2.0) equalizer (~> 0.0.9) @@ -285,14 +287,14 @@ GEM po_to_json (>= 1.0.0) rails (>= 3.2.0) gherkin-ruby (0.3.2) - gitaly-proto (0.84.0) + gitaly-proto (0.88.0) google-protobuf (~> 3.1) grpc (~> 1.0) - github-linguist (4.7.6) - charlock_holmes (~> 0.7.3) + github-linguist (5.3.3) + charlock_holmes (~> 0.7.5) escape_utils (~> 1.1.0) mime-types (>= 1.19) - rugged (>= 0.23.0b) + rugged (>= 0.25.1) github-markup (1.6.1) gitlab-flowdock-git-hook (1.0.1) flowdock (~> 0.7) @@ -343,9 +345,9 @@ GEM google-protobuf (3.5.1) googleapis-common-protos-types (1.0.1) google-protobuf (~> 3.0) - googleauth (0.5.3) + googleauth (0.6.2) faraday (~> 0.12) - jwt (~> 1.4) + jwt (>= 1.4, < 3.0) logging (~> 2.0) memoist (~> 0.12) multi_json (~> 1.11) @@ -369,7 +371,7 @@ GEM rake grape_logging (1.7.0) grape - grpc (1.8.3) + grpc (1.10.0) google-protobuf (~> 3.1) googleapis-common-protos-types (~> 1.0.0) googleauth (>= 0.5.1, < 0.7) @@ -503,7 +505,7 @@ GEM mini_portile2 (2.3.0) minitest (5.7.0) mousetrap-rails (1.4.6) - multi_json (1.12.2) + multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) mustermann (1.0.0) @@ -601,7 +603,7 @@ GEM atomic (>= 1.0.0) mysql2 peek - peek-performance_bar (1.3.0) + peek-performance_bar (1.3.1) peek (>= 0.1.0) peek-pg (1.3.0) concurrent-ruby @@ -646,7 +648,7 @@ GEM pry (~> 0.10) pry-rails (0.3.5) pry (>= 0.9.10) - public_suffix (3.0.0) + public_suffix (3.0.2) pyu-ruby-sasl (0.0.3.3) rack (1.6.8) rack-accept (0.4.5) @@ -797,6 +799,8 @@ GEM rubocop (>= 0.51) rubocop-rspec (1.22.1) rubocop (>= 0.52.1) + ruby-enum (0.7.2) + i18n ruby-fogbugz (0.2.1) crack (~> 0.4) ruby-prof (0.16.2) @@ -858,10 +862,10 @@ GEM sidekiq (>= 4.2.1) sidekiq-limit_fetch (3.4.0) sidekiq (>= 4) - signet (0.7.3) + signet (0.8.1) addressable (~> 2.3) faraday (~> 0.9) - jwt (~> 1.5) + jwt (>= 1.5, < 3.0) multi_json (~> 1.10) simple_po_parser (1.1.2) simplecov (0.14.1) @@ -895,6 +899,7 @@ GEM activesupport (>= 4.0) sprockets (>= 3.0.0) sqlite3 (1.3.13) + sshkey (1.9.0) stackprof (0.2.10) state_machines (0.4.0) state_machines-activemodel (0.4.0) @@ -923,7 +928,7 @@ GEM timfel-krb5-auth (0.8.3) toml (0.1.2) parslet (~> 1.5.0) - toml-rb (0.3.15) + toml-rb (1.0.0) citrus (~> 3.0, > 3.0) truncato (0.7.10) htmlentities (~> 4.3.1) @@ -1018,6 +1023,7 @@ DEPENDENCIES charlock_holmes (~> 0.7.5) chronic (~> 0.10.2) chronic_duration (~> 0.10.6) + commonmarker (~> 0.17) concurrent-ruby (~> 1.0.5) connection_pool (~> 2.0) creole (~> 0.5.0) @@ -1056,8 +1062,8 @@ DEPENDENCIES gettext (~> 3.2.2) gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails_js (~> 1.2.0) - gitaly-proto (~> 0.84.0) - github-linguist (~> 4.7.0) + gitaly-proto (~> 0.88.0) + github-linguist (~> 5.3.3) gitlab-flowdock-git-hook (~> 1.0.1) gitlab-markup (~> 1.6.2) gitlab-styles (~> 2.3) @@ -1072,6 +1078,7 @@ DEPENDENCIES grape-entity (~> 0.6.0) grape-route-helpers (~> 2.1.0) grape_logging (~> 1.7) + grpc (~> 1.10.0) haml_lint (~> 0.26.0) hamlit (~> 2.6.1) hashie-forbidden_attributes @@ -1192,6 +1199,7 @@ DEPENDENCIES spring-commands-rspec (~> 1.0.4) spring-commands-spinach (~> 1.1.0) sprockets (~> 3.7.0) + sshkey (~> 1.9.0) stackprof (~> 0.2.10) state_machines-activerecord (~> 0.4.0) sys-filesystem (~> 1.1.6) @@ -1199,7 +1207,7 @@ DEPENDENCIES test_after_commit (~> 1.1) thin (~> 1.7.0) timecop (~> 0.8.0) - toml-rb (~> 0.3.15) + toml-rb (~> 1.0.0) truncato (~> 0.7.9) u2f (~> 0.2.1) uglifier (~> 2.7.2) diff --git a/PROCESS.md b/PROCESS.md index 99af3be7f1..5ae191840f 100644 --- a/PROCESS.md +++ b/PROCESS.md @@ -71,11 +71,15 @@ star, smile, etc.). Some good tips about code reviews can be found in our ## Feature freeze on the 7th for the release on the 22nd -After the 7th (Pacific Standard Time Zone) of each month, RC1 of the upcoming release (to be shipped on the 22nd) is created and deployed to GitLab.com and the stable branch for this release is frozen, which means master is no longer merged into it. +After 7th at 23:59 (Pacific Time Zone) of each month, RC1 of the upcoming release (to be shipped on the 22nd) is created and deployed to GitLab.com and the stable branch for this release is frozen, which means master is no longer merged into it. Merge requests may still be merged into master during this period, but they will go into the _next_ release, unless they are manually cherry-picked into the stable branch. + By freezing the stable branches 2 weeks prior to a release, we reduce the risk of a last minute merge request potentially breaking things. +Any release candidate that gets created after this date can become a final release, +hence the name release candidate. + ### Between the 1st and the 7th These types of merge requests for the upcoming release need special consideration: @@ -193,11 +197,10 @@ to be backported down to the `9.5` release, you will need to assign it the ### Asking for an exception If you think a merge request should go into an RC or patch even though it does not meet these requirements, -you can ask for an exception to be made. Exceptions require sign-off from 3 people besides the developer: +you can ask for an exception to be made. -1. a Release Manager -2. an Engineering Lead -3. an Engineering Director, the VP of Engineering, or the CTO +Go to [Release tasks issue tracker](https://gitlab.com/gitlab-org/release/tasks/issues/new) and create an issue +using the `Exception-request` issue template. You can find who is who on the [team page](https://about.gitlab.com/team/). diff --git a/VERSION b/VERSION index 3b24057083..d1dd3f904c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -10.5.6 +10.6.0 diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index 1f34c6b50c..464611f66f 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -9,7 +9,7 @@ const Api = { projectsPath: '/api/:version/projects.json', projectPath: '/api/:version/projects/:id', projectLabelsPath: '/:namespace_path/:project_path/labels', - groupLabelsPath: '/groups/:namespace_path/labels', + groupLabelsPath: '/groups/:namespace_path/-/labels', licensePath: '/api/:version/templates/licenses/:key', gitignorePath: '/api/:version/templates/gitignores/:key', gitlabCiYmlPath: '/api/:version/templates/gitlab_ci_ymls/:key', @@ -32,7 +32,7 @@ const Api = { }, // Return groups list. Filtered by query - groups(query, options, callback) { + groups(query, options, callback = $.noop) { const url = Api.buildUrl(Api.groupsPath); return axios.get(url, { params: Object.assign({ diff --git a/app/assets/javascripts/autosave.js b/app/assets/javascripts/autosave.js index 0f28bd233a..0da872db7e 100644 --- a/app/assets/javascripts/autosave.js +++ b/app/assets/javascripts/autosave.js @@ -3,10 +3,10 @@ import AccessorUtilities from './lib/utils/accessor'; export default class Autosave { - constructor(field, key, resource) { + constructor(field, key) { this.field = field; + this.isLocalStorageAvailable = AccessorUtilities.isLocalStorageAccessSafe(); - this.resource = resource; if (key.join != null) { key = key.join('/'); } @@ -17,31 +17,27 @@ export default class Autosave { } restore() { - var text; - if (!this.isLocalStorageAvailable) return; + if (!this.field.length) return; - text = window.localStorage.getItem(this.key); + const text = window.localStorage.getItem(this.key); if ((text != null ? text.length : void 0) > 0) { this.field.val(text); } - if (!this.resource && this.resource !== 'issue') { - this.field.trigger('input'); - } else { - // v-model does not update with jQuery trigger - // https://github.com/vuejs/vue/issues/2804#issuecomment-216968137 - const event = new Event('change', { bubbles: true, cancelable: false }); - const field = this.field.get(0); - if (field) { - field.dispatchEvent(event); - } - } + + this.field.trigger('input'); + // v-model does not update with jQuery trigger + // https://github.com/vuejs/vue/issues/2804#issuecomment-216968137 + const event = new Event('change', { bubbles: true, cancelable: false }); + const field = this.field.get(0); + field.dispatchEvent(event); } save() { - var text; - text = this.field.val(); + if (!this.field.length) return; + + const text = this.field.val(); if (this.isLocalStorageAvailable && (text != null ? text.length : void 0) > 0) { return window.localStorage.setItem(this.key, text); diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js index 87109a802e..26e62732b3 100644 --- a/app/assets/javascripts/awards_handler.js +++ b/app/assets/javascripts/awards_handler.js @@ -2,7 +2,7 @@ import _ from 'underscore'; import Cookies from 'js-cookie'; import { __ } from './locale'; -import { isInIssuePage, updateTooltipTitle } from './lib/utils/common_utils'; +import { isInIssuePage, isInMRPage, hasVueMRDiscussionsCookie, updateTooltipTitle } from './lib/utils/common_utils'; import flash from './flash'; import axios from './lib/utils/axios_utils'; @@ -50,10 +50,8 @@ class AwardsHandler { this.registerEventListener('on', $('html'), 'click', (e) => { const $target = $(e.target); - if (!$target.closest('.emoji-menu-content').length) { - $('.js-awards-block.current').removeClass('current'); - } if (!$target.closest('.emoji-menu').length) { + $('.js-awards-block.current').removeClass('current'); if ($('.emoji-menu').is(':visible')) { $('.js-add-award.is-active').removeClass('is-active'); this.hideMenuElement($('.emoji-menu')); @@ -241,9 +239,9 @@ class AwardsHandler { } addAward(votesBlock, awardUrl, emoji, checkMutuality, callback) { - const isMainAwardsBlock = votesBlock.closest('.js-issue-note-awards').length; + const isMainAwardsBlock = votesBlock.closest('.js-noteable-awards').length; - if (isInIssuePage() && !isMainAwardsBlock) { + if (this.isInVueNoteablePage() && !isMainAwardsBlock) { const id = votesBlock.attr('id').replace('note_', ''); this.hideMenuElement($('.emoji-menu')); @@ -295,8 +293,16 @@ class AwardsHandler { } } + isVueMRDiscussions() { + return isInMRPage() && hasVueMRDiscussionsCookie() && !$('#diffs').is(':visible'); + } + + isInVueNoteablePage() { + return isInIssuePage() || this.isVueMRDiscussions(); + } + getVotesBlock() { - if (isInIssuePage()) { + if (this.isInVueNoteablePage()) { const $el = $('.js-add-award.is-active').closest('.note.timeline-entry'); if ($el.length) { @@ -314,7 +320,7 @@ class AwardsHandler { } getAwardUrl() { - return this.getVotesBlock().data('award-url'); + return this.getVotesBlock().data('awardUrl'); } checkMutuality(votesBlock, emoji) { diff --git a/app/assets/javascripts/behaviors/copy_to_clipboard.js b/app/assets/javascripts/behaviors/copy_to_clipboard.js index cdea625fc8..b669b63d23 100644 --- a/app/assets/javascripts/behaviors/copy_to_clipboard.js +++ b/app/assets/javascripts/behaviors/copy_to_clipboard.js @@ -2,7 +2,7 @@ import Clipboard from 'clipboard'; function showTooltip(target, title) { const $target = $(target); - const originalTitle = $target.data('original-title'); + const originalTitle = $target.data('originalTitle'); if (!$target.data('hideTooltip')) { $target diff --git a/app/assets/javascripts/behaviors/quick_submit.js b/app/assets/javascripts/behaviors/quick_submit.js index 2cf8f4fa93..312edc0cd6 100644 --- a/app/assets/javascripts/behaviors/quick_submit.js +++ b/app/assets/javascripts/behaviors/quick_submit.js @@ -43,7 +43,7 @@ $(document).on('keydown.quick_submit', '.js-quick-submit', (e) => { const $form = $(e.target).closest('form'); const $submitButton = $form.find('input[type=submit], button[type=submit]').first(); - if (!$submitButton.attr('disabled')) { + if (!$submitButton.prop('disabled')) { $submitButton.trigger('click', [e]); if (!isInIssuePage()) { diff --git a/app/assets/javascripts/behaviors/requires_input.js b/app/assets/javascripts/behaviors/requires_input.js index 035a7e5c43..e10cb2e3dc 100644 --- a/app/assets/javascripts/behaviors/requires_input.js +++ b/app/assets/javascripts/behaviors/requires_input.js @@ -40,7 +40,7 @@ $.fn.requiresInput = function requiresInput() { // based on the option selected function hideOrShowHelpBlock(form) { const selected = $('.js-select-namespace option:selected'); - if (selected.length && selected.data('options-parent') === 'groups') { + if (selected.length && selected.data('optionsParent') === 'groups') { form.find('.help-block').hide(); } else if (selected.length) { form.find('.help-block').show(); diff --git a/app/assets/javascripts/behaviors/toggler_behavior.js b/app/assets/javascripts/behaviors/toggler_behavior.js index 417ac31fc8..81c8944142 100644 --- a/app/assets/javascripts/behaviors/toggler_behavior.js +++ b/app/assets/javascripts/behaviors/toggler_behavior.js @@ -12,7 +12,7 @@ $(() => { const $container = $(container); $container - .find('.js-toggle-button .fa') + .find('.js-toggle-button .fa-chevron-up, .js-toggle-button .fa-chevron-down') .toggleClass('fa-chevron-up', toggleState) .toggleClass('fa-chevron-down', toggleState !== undefined ? !toggleState : undefined); @@ -22,7 +22,7 @@ $(() => { } $('body').on('click', '.js-toggle-button', function toggleButton(e) { - e.target.classList.toggle('open'); + e.currentTarget.classList.toggle(e.currentTarget.dataset.toggleOpenClass || 'open'); toggleContainer($(this).closest('.js-toggle-container')); const targetTag = e.currentTarget.tagName.toLowerCase(); diff --git a/app/assets/javascripts/blob/balsamiq_viewer.js b/app/assets/javascripts/blob/balsamiq_viewer.js index 062577af38..06ef86ecb7 100644 --- a/app/assets/javascripts/blob/balsamiq_viewer.js +++ b/app/assets/javascripts/blob/balsamiq_viewer.js @@ -7,7 +7,7 @@ function onError() { return flash; } -function loadBalsamiqFile() { +export default function loadBalsamiqFile() { const viewer = document.getElementById('js-balsamiq-viewer'); if (!(viewer instanceof Element)) return; @@ -17,5 +17,3 @@ function loadBalsamiqFile() { const balsamiqViewer = new BalsamiqViewer(viewer); balsamiqViewer.loadFile(endpoint).catch(onError); } - -$(loadBalsamiqFile); diff --git a/app/assets/javascripts/blob/notebook_viewer.js b/app/assets/javascripts/blob/notebook_viewer.js index b7a0a195a9..226ae69893 100644 --- a/app/assets/javascripts/blob/notebook_viewer.js +++ b/app/assets/javascripts/blob/notebook_viewer.js @@ -1,3 +1,3 @@ import renderNotebook from './notebook'; -document.addEventListener('DOMContentLoaded', renderNotebook); +export default renderNotebook; diff --git a/app/assets/javascripts/blob/pdf_viewer.js b/app/assets/javascripts/blob/pdf_viewer.js index 91abe9dd69..cabbb396ea 100644 --- a/app/assets/javascripts/blob/pdf_viewer.js +++ b/app/assets/javascripts/blob/pdf_viewer.js @@ -1,3 +1,3 @@ import renderPDF from './pdf'; -document.addEventListener('DOMContentLoaded', renderPDF); +export default renderPDF; diff --git a/app/assets/javascripts/blob/sketch_viewer.js b/app/assets/javascripts/blob/sketch_viewer.js index 0640dd2685..2c1c6339fd 100644 --- a/app/assets/javascripts/blob/sketch_viewer.js +++ b/app/assets/javascripts/blob/sketch_viewer.js @@ -1,8 +1,8 @@ /* eslint-disable no-new */ import SketchLoader from './sketch'; -document.addEventListener('DOMContentLoaded', () => { +export default () => { const el = document.getElementById('js-sketch-viewer'); new SketchLoader(el); -}); +}; diff --git a/app/assets/javascripts/blob/stl_viewer.js b/app/assets/javascripts/blob/stl_viewer.js index f611c4fe64..63236b6477 100644 --- a/app/assets/javascripts/blob/stl_viewer.js +++ b/app/assets/javascripts/blob/stl_viewer.js @@ -1,6 +1,6 @@ import Renderer from './3d_viewer'; -document.addEventListener('DOMContentLoaded', () => { +export default () => { const viewer = new Renderer(document.getElementById('js-stl-viewer')); [].slice.call(document.querySelectorAll('.js-material-changer')).forEach((el) => { @@ -16,4 +16,4 @@ document.addEventListener('DOMContentLoaded', () => { viewer.changeObjectMaterials(target.dataset.type); }); }); -}); +}; diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js index 612f604e72..92ea91c45a 100644 --- a/app/assets/javascripts/blob/viewer/index.js +++ b/app/assets/javascripts/blob/viewer/index.js @@ -5,6 +5,7 @@ import axios from '../../lib/utils/axios_utils'; export default class BlobViewer { constructor() { BlobViewer.initAuxiliaryViewer(); + BlobViewer.initRichViewer(); this.initMainViewers(); } @@ -16,6 +17,38 @@ export default class BlobViewer { BlobViewer.loadViewer(auxiliaryViewer); } + static initRichViewer() { + const viewer = document.querySelector('.blob-viewer[data-type="rich"]'); + if (!viewer || !viewer.dataset.richType) return; + + const initViewer = promise => promise + .then(module => module.default(viewer)) + .catch((error) => { + Flash('Error loading file viewer.'); + throw error; + }); + + switch (viewer.dataset.richType) { + case 'balsamiq': + initViewer(import(/* webpackChunkName: 'balsamiq_viewer' */ '../balsamiq_viewer')); + break; + case 'notebook': + initViewer(import(/* webpackChunkName: 'notebook_viewer' */ '../notebook_viewer')); + break; + case 'pdf': + initViewer(import(/* webpackChunkName: 'pdf_viewer' */ '../pdf_viewer')); + break; + case 'sketch': + initViewer(import(/* webpackChunkName: 'sketch_viewer' */ '../sketch_viewer')); + break; + case 'stl': + initViewer(import(/* webpackChunkName: 'stl_viewer' */ '../stl_viewer')); + break; + default: + break; + } + } + initMainViewers() { this.$fileHolder = $('.file-holder'); if (!this.$fileHolder.length) return; diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js index 6b06344f5b..931ed042df 100644 --- a/app/assets/javascripts/blob_edit/blob_bundle.js +++ b/app/assets/javascripts/blob_edit/blob_bundle.js @@ -4,16 +4,16 @@ import NewCommitForm from '../new_commit_form'; import EditBlob from './edit_blob'; import BlobFileDropzone from '../blob/blob_file_dropzone'; -$(() => { +export default () => { const editBlobForm = $('.js-edit-blob-form'); const uploadBlobForm = $('.js-upload-blob-form'); const deleteBlobForm = $('.js-delete-blob-form'); if (editBlobForm.length) { - const urlRoot = editBlobForm.data('relative-url-root'); - const assetsPath = editBlobForm.data('assets-prefix'); - const blobLanguage = editBlobForm.data('blob-language'); - const currentAction = $('.js-file-title').data('current-action'); + const urlRoot = editBlobForm.data('relativeUrlRoot'); + const assetsPath = editBlobForm.data('assetsPrefix'); + const blobLanguage = editBlobForm.data('blobLanguage'); + const currentAction = $('.js-file-title').data('currentAction'); new EditBlob(`${urlRoot}${assetsPath}`, blobLanguage, currentAction); new NewCommitForm(editBlobForm); @@ -34,4 +34,4 @@ $(() => { if (deleteBlobForm.length) { new NewCommitForm(deleteBlobForm); } -}); +}; diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js index a25f7fb3dc..d4f6adaccb 100644 --- a/app/assets/javascripts/blob_edit/edit_blob.js +++ b/app/assets/javascripts/blob_edit/edit_blob.js @@ -59,7 +59,7 @@ export default class EditBlob { if (paneId === '#preview') { this.$toggleButton.hide(); - axios.post(currentLink.data('preview-url'), { + axios.post(currentLink.data('previewUrl'), { content: this.editor.getValue(), }) .then(({ data }) => { diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue index 23fec50358..84885ca930 100644 --- a/app/assets/javascripts/boards/components/board_card.vue +++ b/app/assets/javascripts/boards/components/board_card.vue @@ -1,4 +1,5 @@ + + + diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js index 983429550f..9501e35b17 100644 --- a/app/assets/javascripts/boards/components/board_sidebar.js +++ b/app/assets/javascripts/boards/components/board_sidebar.js @@ -2,10 +2,11 @@ import Vue from 'vue'; import Flash from '../../flash'; +import { __ } from '../../locale'; import Sidebar from '../../right_sidebar'; import eventHub from '../../sidebar/event_hub'; import assigneeTitle from '../../sidebar/components/assignees/assignee_title'; -import assignees from '../../sidebar/components/assignees/assignees'; +import assignees from '../../sidebar/components/assignees/assignees.vue'; import DueDateSelectors from '../../due_date_select'; import './sidebar/remove_issue'; import IssuableContext from '../../issuable_context'; @@ -95,7 +96,7 @@ gl.issueBoards.BoardSidebar = Vue.extend({ }) .catch(() => { this.loadingAssignees = false; - return new Flash('An error occurred while saving assignees'); + Flash(__('An error occurred while saving assignees')); }); }, }, diff --git a/app/assets/javascripts/boards/components/issue_card_inner.js b/app/assets/javascripts/boards/components/issue_card_inner.js index bf47487902..fc2bad2415 100644 --- a/app/assets/javascripts/boards/components/issue_card_inner.js +++ b/app/assets/javascripts/boards/components/issue_card_inner.js @@ -31,6 +31,10 @@ gl.issueBoards.IssueCardInner = Vue.extend({ required: false, default: false, }, + groupId: { + type: Number, + required: false, + }, }, data() { return { @@ -64,7 +68,13 @@ gl.issueBoards.IssueCardInner = Vue.extend({ return this.issue.assignees.length > this.numberOverLimit; }, cardUrl() { - return `${this.issueLinkBase}/${this.issue.iid}`; + let baseUrl = this.issueLinkBase; + + if (this.groupId && this.issue.project) { + baseUrl = this.issueLinkBase.replace(':project_path', this.issue.project.path); + } + + return `${baseUrl}/${this.issue.iid}`; }, issueId() { if (this.issue.iid) { @@ -148,7 +158,7 @@ gl.issueBoards.IssueCardInner = Vue.extend({ class="card-number" v-if="issueId" > - {{ issueId }} + {{ issueId }}
diff --git a/app/assets/javascripts/boards/components/modal/footer.js b/app/assets/javascripts/boards/components/modal/footer.js index 182957113a..03cd7ef65c 100644 --- a/app/assets/javascripts/boards/components/modal/footer.js +++ b/app/assets/javascripts/boards/components/modal/footer.js @@ -1,7 +1,6 @@ -/* eslint-disable no-new */ - import Vue from 'vue'; import Flash from '../../../flash'; +import { __ } from '../../../locale'; import './lists_dropdown'; import { pluralize } from '../../../lib/utils/text_utility'; @@ -36,7 +35,7 @@ gl.issueBoards.ModalFooter = Vue.extend({ gl.boardService.bulkUpdate(issueIds, { add_label_ids: [list.label.id], }).catch(() => { - new Flash('Failed to update issues, please try again.', 'alert'); + Flash(__('Failed to update issues, please try again.')); selectedIssues.forEach((issue) => { list.removeIssue(issue); diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js b/app/assets/javascripts/boards/components/new_list_dropdown.js index c19c989680..362ef43e6f 100644 --- a/app/assets/javascripts/boards/components/new_list_dropdown.js +++ b/app/assets/javascripts/boards/components/new_list_dropdown.js @@ -1,5 +1,6 @@ /* eslint-disable func-names, no-new, space-before-function-paren, one-var, promise/catch-or-return */ +import axios from '~/lib/utils/axios_utils'; import _ from 'underscore'; import CreateLabelDropdown from '../../create_label'; @@ -24,13 +25,13 @@ $(document).off('created.label').on('created.label', (e, label) => { gl.issueBoards.newListDropdownInit = () => { $('.js-new-board-list').each(function () { const $this = $(this); - new CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('namespace-path'), $this.data('project-path')); + new CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('namespacePath'), $this.data('projectPath')); $this.glDropdown({ data(term, callback) { - $.get($this.attr('data-list-labels-path')) - .then((resp) => { - callback(resp); + axios.get($this.attr('data-list-labels-path')) + .then(({ data }) => { + callback(data); }); }, renderRow (label) { diff --git a/app/assets/javascripts/boards/components/project_select.vue b/app/assets/javascripts/boards/components/project_select.vue new file mode 100644 index 0000000000..d99b222c30 --- /dev/null +++ b/app/assets/javascripts/boards/components/project_select.vue @@ -0,0 +1,127 @@ + + + diff --git a/app/assets/javascripts/boards/components/sidebar/remove_issue.js b/app/assets/javascripts/boards/components/sidebar/remove_issue.js index 1ad9721193..09c683ff62 100644 --- a/app/assets/javascripts/boards/components/sidebar/remove_issue.js +++ b/app/assets/javascripts/boards/components/sidebar/remove_issue.js @@ -1,7 +1,6 @@ -/* eslint-disable no-new */ - import Vue from 'vue'; import Flash from '../../../flash'; +import { __ } from '../../../locale'; const Store = gl.issueBoards.BoardsStore; @@ -25,7 +24,7 @@ gl.issueBoards.RemoveIssueBtn = Vue.extend({ }, computed: { updateUrl() { - return this.issueUpdate; + return this.issueUpdate.replace(':project_path', this.issue.project.path); }, }, methods: { @@ -33,19 +32,23 @@ gl.issueBoards.RemoveIssueBtn = Vue.extend({ const issue = this.issue; const lists = issue.getLists(); const listLabelIds = lists.map(list => list.label.id); - let labelIds = this.issue.labels + + let labelIds = issue.labels .map(label => label.id) .filter(id => !listLabelIds.includes(id)); if (labelIds.length === 0) { labelIds = ['']; } + const data = { issue: { label_ids: labelIds, }, }; + + // Post the remove data Vue.http.patch(this.updateUrl, data).catch(() => { - new Flash('Failed to remove issue from board, please try again.', 'alert'); + Flash(__('Failed to remove issue from board, please try again.')); lists.forEach((list) => { list.addIssue(issue); diff --git a/app/assets/javascripts/boards/filtered_search_boards.js b/app/assets/javascripts/boards/filtered_search_boards.js index 184665f395..fb40b9f556 100644 --- a/app/assets/javascripts/boards/filtered_search_boards.js +++ b/app/assets/javascripts/boards/filtered_search_boards.js @@ -1,9 +1,13 @@ /* eslint-disable class-methods-use-this */ import FilteredSearchContainer from '../filtered_search/container'; +import FilteredSearchManager from '../filtered_search/filtered_search_manager'; -export default class FilteredSearchBoards extends gl.FilteredSearchManager { +export default class FilteredSearchBoards extends FilteredSearchManager { constructor(store, updateUrl = false, cantEdit = []) { - super('boards'); + super({ + page: 'boards', + stateFiltersSelector: '.issues-state-filters', + }); this.store = store; this.updateUrl = updateUrl; diff --git a/app/assets/javascripts/boards/boards_bundle.js b/app/assets/javascripts/boards/index.js similarity index 94% rename from app/assets/javascripts/boards/boards_bundle.js rename to app/assets/javascripts/boards/index.js index 90166b3d3d..efc0da2e7a 100644 --- a/app/assets/javascripts/boards/boards_bundle.js +++ b/app/assets/javascripts/boards/index.js @@ -2,15 +2,18 @@ import _ from 'underscore'; import Vue from 'vue'; -import Flash from '../flash'; -import { __ } from '../locale'; + +import Flash from '~/flash'; +import { __ } from '~/locale'; +import '~/vue_shared/models/label'; + import FilteredSearchBoards from './filtered_search_boards'; import eventHub from './eventhub'; -import sidebarEventHub from '../sidebar/event_hub'; +import sidebarEventHub from '~/sidebar/event_hub'; // eslint-disable-line import/first import './models/issue'; -import './models/label'; import './models/list'; import './models/milestone'; +import './models/project'; import './models/assignee'; import './stores/boards_store'; import './stores/modal_store'; @@ -22,9 +25,9 @@ import './components/board'; import './components/board_sidebar'; import './components/new_list_dropdown'; import './components/modal/index'; -import '../vue_shared/vue_resource_interceptor'; +import '~/vue_shared/vue_resource_interceptor'; // eslint-disable-line import/first -$(() => { +export default () => { const $boardApp = document.getElementById('board-app'); const Store = gl.issueBoards.BoardsStore; const ModalStore = gl.issueBoards.ModalStore; @@ -87,7 +90,7 @@ $(() => { sidebarEventHub.$off('toggleSubscription', this.toggleSubscription); }, mounted () { - this.filterManager = new FilteredSearchBoards(Store.filter, true); + this.filterManager = new FilteredSearchBoards(Store.filter, true, Store.cantEdit); this.filterManager.setup(); Store.disabled = this.disabled; @@ -177,6 +180,7 @@ $(() => { return { modal: ModalStore.store, store: Store.state, + canAdminList: this.$options.el.hasAttribute('data-can-admin-list'), }; }, computed: { @@ -230,10 +234,11 @@ $(() => { :class="{ 'disabled': disabled }" :title="tooltipTitle" :aria-disabled="disabled" + v-if="canAdminList" @click="openModal"> Add issues
`, }); -}); +}; diff --git a/app/assets/javascripts/boards/mixins/sortable_default_options.js b/app/assets/javascripts/boards/mixins/sortable_default_options.js index 38a0eb12f9..5e31c6314b 100644 --- a/app/assets/javascripts/boards/mixins/sortable_default_options.js +++ b/app/assets/javascripts/boards/mixins/sortable_default_options.js @@ -1,6 +1,8 @@ /* eslint-disable no-unused-vars, no-mixed-operators, comma-dangle */ /* global DocumentTouch */ +import sortableConfig from '../../sortable/sortable_config'; + window.gl = window.gl || {}; window.gl.issueBoards = window.gl.issueBoards || {}; @@ -18,19 +20,14 @@ gl.issueBoards.onEnd = () => { gl.issueBoards.touchEnabled = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch; gl.issueBoards.getBoardSortableDefaultOptions = (obj) => { - const defaultSortOptions = { - animation: 200, - forceFallback: true, - fallbackClass: 'is-dragging', - fallbackOnBody: true, - ghostClass: 'is-ghost', + const defaultSortOptions = Object.assign({}, sortableConfig, { filter: '.board-delete, .btn', delay: gl.issueBoards.touchEnabled ? 100 : 0, scrollSensitivity: gl.issueBoards.touchEnabled ? 60 : 100, scrollSpeed: 20, onStart: gl.issueBoards.onStart, - onEnd: gl.issueBoards.onEnd - }; + onEnd: gl.issueBoards.onEnd, + }); Object.keys(obj).forEach((key) => { defaultSortOptions[key] = obj[key]; }); return defaultSortOptions; diff --git a/app/assets/javascripts/boards/models/issue.js b/app/assets/javascripts/boards/models/issue.js index 81edd95bf2..4c5079efc8 100644 --- a/app/assets/javascripts/boards/models/issue.js +++ b/app/assets/javascripts/boards/models/issue.js @@ -4,6 +4,7 @@ /* global ListAssignee */ import Vue from 'vue'; +import IssueProject from './project'; class ListIssue { constructor (obj, defaultAvatar) { @@ -23,6 +24,12 @@ class ListIssue { this.isLoading = {}; this.sidebarInfoEndpoint = obj.issue_sidebar_endpoint; this.toggleSubscriptionEndpoint = obj.toggle_subscription_endpoint; + this.milestone_id = obj.milestone_id; + this.project_id = obj.project_id; + + if (obj.project) { + this.project = new IssueProject(obj.project); + } if (obj.milestone) { this.milestone = new ListMilestone(obj.milestone); @@ -105,8 +112,11 @@ class ListIssue { data.issue.label_ids = ['']; } - return Vue.http.patch(url, data); + const projectPath = this.project ? this.project.path : ''; + return Vue.http.patch(url.replace(':project_path', projectPath), data); } } window.ListIssue = ListIssue; + +export default ListIssue; diff --git a/app/assets/javascripts/boards/models/project.js b/app/assets/javascripts/boards/models/project.js new file mode 100644 index 0000000000..a3d5c7af7a --- /dev/null +++ b/app/assets/javascripts/boards/models/project.js @@ -0,0 +1,6 @@ +export default class IssueProject { + constructor(obj) { + this.id = obj.id; + this.path = obj.path; + } +} diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js index 798d7e0d14..348cdeec73 100644 --- a/app/assets/javascripts/boards/stores/boards_store.js +++ b/app/assets/javascripts/boards/stores/boards_store.js @@ -2,7 +2,7 @@ /* global List */ import _ from 'underscore'; import Cookies from 'js-cookie'; -import { getUrlParamsArray } from '../../lib/utils/common_utils'; +import { getUrlParamsArray } from '~/lib/utils/common_utils'; window.gl = window.gl || {}; window.gl.issueBoards = window.gl.issueBoards || {}; diff --git a/app/assets/javascripts/ci_variable_list/ajax_variable_list.js b/app/assets/javascripts/ci_variable_list/ajax_variable_list.js index 76f93e5c6b..b33adff609 100644 --- a/app/assets/javascripts/ci_variable_list/ajax_variable_list.js +++ b/app/assets/javascripts/ci_variable_list/ajax_variable_list.js @@ -75,6 +75,7 @@ export default class AjaxVariableList { if (res.status === statusCodes.OK && res.data) { this.updateRowsWithPersistedVariables(res.data.variables); + this.variableList.hideValues(); } else if (res.status === statusCodes.BAD_REQUEST) { // Validation failed this.errorBox.innerHTML = generateErrorBoxContent(res.data); diff --git a/app/assets/javascripts/ci_variable_list/ci_variable_list.js b/app/assets/javascripts/ci_variable_list/ci_variable_list.js index 3467e88119..745f340429 100644 --- a/app/assets/javascripts/ci_variable_list/ci_variable_list.js +++ b/app/assets/javascripts/ci_variable_list/ci_variable_list.js @@ -178,6 +178,10 @@ export default class VariableList { this.$container.find('.js-row-remove-button').attr('disabled', !isEnabled); } + hideValues() { + this.secretValues.updateDom(false); + } + getAllData() { // Ignore the last empty row because we don't want to try persist // a blank variable and run into validation problems. diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js index b070a59cf1..01aec4f36a 100644 --- a/app/assets/javascripts/clusters/clusters_bundle.js +++ b/app/assets/javascripts/clusters/clusters_bundle.js @@ -37,10 +37,11 @@ export default class Clusters { clusterStatusReason, helpPath, ingressHelpPath, + ingressDnsHelpPath, } = document.querySelector('.js-edit-cluster-form').dataset; this.store = new ClustersStore(); - this.store.setHelpPaths(helpPath, ingressHelpPath); + this.store.setHelpPaths(helpPath, ingressHelpPath, ingressDnsHelpPath); this.store.setManagePrometheusPath(managePrometheusPath); this.store.updateStatus(clusterStatus); this.store.updateStatusReason(clusterStatusReason); @@ -98,6 +99,7 @@ export default class Clusters { helpPath: this.state.helpPath, ingressHelpPath: this.state.ingressHelpPath, managePrometheusPath: this.state.managePrometheusPath, + ingressDnsHelpPath: this.state.ingressDnsHelpPath, }, }); }, diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue index 50e35bbbba..c2a35341eb 100644 --- a/app/assets/javascripts/clusters/components/application_row.vue +++ b/app/assets/javascripts/clusters/components/application_row.vue @@ -36,10 +36,6 @@ type: String, required: false, }, - description: { - type: String, - required: true, - }, status: { type: String, required: false, @@ -148,7 +144,7 @@ class="table-section section-wrap" role="gridcell" > -
+