New upstream version 12.0.8

This commit is contained in:
Sruthi Chandran 2019-09-04 21:01:54 +05:30
parent e2a27f7d09
commit 400b49096b
2813 changed files with 200989 additions and 45768 deletions

View file

@ -8,11 +8,13 @@ globals:
plugins:
- import
- html
- "@gitlab/i18n"
settings:
import/resolver:
webpack:
config: './config/webpack.config.js'
rules:
"@gitlab/i18n/no-non-i18n-strings": error
import/no-commonjs: error
no-underscore-dangle:
- error
@ -31,3 +33,11 @@ rules:
vue/no-use-v-if-with-v-for: off
vue/no-v-html: off
vue/use-v-on-exact: off
overrides:
files:
# Vue is temporarily being disabled until the autofix errors are resolved
# Follow up issue https://gitlab.com/gitlab-org/gitlab-ce/issues/57969
- '*.vue'
- '**/spec/**/*'
rules:
"@gitlab/i18n/no-non-i18n-strings": off

1
.gitignore vendored
View file

@ -79,3 +79,4 @@ package-lock.json
/junit_*.xml
/coverage-frontend/
jsdoc/
**/tmp/rubocop_cache/**

View file

@ -1,4 +1,4 @@
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-golang-1.11-git-2.21-chrome-73.0-node-10.x-yarn-1.12-postgresql-9.6-graphicsmagick-1.3.29"
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.21-chrome-73.0-node-12.x-yarn-1.16-postgresql-9.6-graphicsmagick-1.3.29"
variables:
MYSQL_ALLOW_EMPTY_PASSWORD: "1"
@ -13,10 +13,8 @@ variables:
BUILD_ASSETS_IMAGE: "false"
before_script:
- bundle --version
- date
- source scripts/utils.sh
- date
- source scripts/prepare_build.sh
- date
@ -46,3 +44,4 @@ include:
- local: .gitlab/ci/review.gitlab-ci.yml
- local: .gitlab/ci/setup.gitlab-ci.yml
- local: .gitlab/ci/test-metadata.gitlab-ci.yml
- local: .gitlab/ci/yaml.gitlab-ci.yml

View file

@ -1,9 +1,9 @@
# Backend Maintainers are the default for all ruby files
*.rb @ashmckenzie @ayufan @dbalexandre @DouweM @dzaporozhets @godfat @grzesiek @mkozono @nick.thomas @rspeicher @rymai @smcgivern @mayra-cabrera
*.rake @ashmckenzie @ayufan @dbalexandre @DouweM @dzaporozhets @godfat @grzesiek @mkozono @nick.thomas @rspeicher @rymai @smcgivern @mayra-cabrera
*.rb @ashmckenzie @ayufan @dbalexandre @DouweM @dzaporozhets @godfat @grzesiek @mkozono @mayra-cabrera @nick.thomas @rspeicher @rymai @reprazent @smcgivern @tkuah
*.rake @ashmckenzie @ayufan @dbalexandre @DouweM @dzaporozhets @godfat @grzesiek @mkozono @mayra-cabrera @nick.thomas @rspeicher @rymai @reprazent @smcgivern @tkuah
# Technical writing team are the default reviewers for everything in `doc/`
/doc/ @axil @marcia
/doc/ @axil @marcia @eread @mikelewis
# Frontend maintainers should see everything in `app/assets/`
app/assets/ @ClemMakesApps @fatihacet @filipa @iamphill @mikegreiling @timzallmann @kushalpandya
@ -18,3 +18,4 @@ db/ @abrandl @NikolayS
/lib/gitlab/auth/ldap/ @dblessing @mkozono
/lib/gitlab/ci/templates/ @nolith @zj
/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml @DylanGriffith @mayra-cabrera @tkuah
/lib/gitlab/ci/templates/Security/ @plafoucriere @gonzoyumo @twoodham

View file

@ -1,5 +1,5 @@
cloud-native-image:
image: ruby:2.5-alpine
image: ruby:2.6-alpine
before_script: []
dependencies: []
stage: post-test

View file

@ -16,7 +16,7 @@
gitlab:assets:compile:
<<: *assets-compile-cache
extends: .dedicated-no-docs-pull-cache-job
image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-git-2.21-chrome-73.0-node-8.x-yarn-1.12-graphicsmagick-1.3.29-docker-18.06.1
image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-git-2.21-chrome-73.0-node-12.x-yarn-1.16-graphicsmagick-1.3.29-docker-18.06.1
dependencies:
- setup-test-env
services:
@ -33,11 +33,12 @@ gitlab:assets:compile:
DOCKER_HOST: tcp://docker:2375
script:
- node --version
- yarn install --frozen-lockfile --production --cache-folder .yarn-cache
- retry yarn install --frozen-lockfile --production --cache-folder .yarn-cache
- free -m
- bundle exec rake gitlab:assets:compile
- retry bundle exec rake gitlab:assets:compile
- time scripts/build_assets_image
- scripts/clean-old-cached-assets
- rm -f /etc/apt/sources.list.d/google*.list # We don't need to update Chrome here
# Play dependent manual jobs
- install_api_client_dependencies_with_apt
- play_job "review-build-cng" || true # this job might not exist so ignore the failure if it cannot be played
@ -64,9 +65,9 @@ compile-assets:
stage: prepare
script:
- node --version
- yarn install --frozen-lockfile --cache-folder .yarn-cache
- retry yarn install --frozen-lockfile --cache-folder .yarn-cache
- free -m
- bundle exec rake gitlab:assets:compile
- retry bundle exec rake gitlab:assets:compile
- scripts/clean-old-cached-assets
variables:
# we override the max_old_space_size to prevent OOM errors

View file

@ -9,7 +9,7 @@
- gitlab-org
.default-cache: &default-cache
key: "debian-stretch-ruby-2.5.3-node-10.x"
key: "debian-stretch-ruby-2.6.3-node-12.x"
paths:
- vendor/ruby
- .yarn-cache/
@ -47,7 +47,7 @@
.single-script-job-dedicated-runner:
extends: .dedicated-runner
image: ruby:2.5-alpine
image: ruby:2.6-alpine
stage: test
cache: {}
dependencies: []

View file

@ -1,4 +1,3 @@
pages:
extends: .dedicated-no-docs-no-db-pull-cache-job
before_script: []

View file

@ -1,6 +1,6 @@
package-and-qa:
image: ruby:2.5-alpine
stage: qa
image: ruby:2.6-alpine
stage: review # So even if review-deploy failed we can still run this
when: manual
before_script: []
dependencies: []

View file

@ -6,8 +6,9 @@
.use-pg-10: &use-pg-10
services:
- postgres:10.7
- redis:alpine
- name: postgres:10.7
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:alpine
.use-mysql: &use-mysql
services:
@ -52,8 +53,10 @@
script:
- JOB_NAME=( $CI_JOB_NAME )
- TEST_TOOL=${JOB_NAME[0]}
- export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${TEST_TOOL}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- export KNAPSACK_GENERATE_REPORT=true
- TEST_LEVEL=${JOB_NAME[1]}
- DATABASE=${JOB_NAME[2]}
- export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${TEST_TOOL}_${TEST_LEVEL}_${DATABASE}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- export KNAPSACK_GENERATE_REPORT=true KNAPSACK_LOG_LEVEL=debug KNAPSACK_TEST_DIR=spec
- export SUITE_FLAKY_RSPEC_REPORT_PATH=${FLAKY_RSPEC_SUITE_REPORT_PATH}
- export FLAKY_RSPEC_REPORT_PATH=rspec_flaky/all_${TEST_TOOL}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- export NEW_FLAKY_RSPEC_REPORT_PATH=rspec_flaky/new_${TEST_TOOL}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
@ -63,7 +66,10 @@
- '[[ -f $FLAKY_RSPEC_REPORT_PATH ]] || echo "{}" > ${FLAKY_RSPEC_REPORT_PATH}'
- '[[ -f $NEW_FLAKY_RSPEC_REPORT_PATH ]] || echo "{}" > ${NEW_FLAKY_RSPEC_REPORT_PATH}'
- scripts/gitaly-test-spawn
- knapsack rspec "--color --format documentation --format RspecJunitFormatter --out junit_rspec.xml"
- date
- 'export KNAPSACK_TEST_FILE_PATTERN=$(ruby -r./lib/quality/test_level.rb -e "puts Quality::TestLevel.new.pattern(:${TEST_LEVEL})")'
- knapsack rspec "--color --format documentation --format RspecJunitFormatter --out junit_rspec.xml --tag level:${TEST_LEVEL} --tag ~geo"
- date
artifacts:
expire_in: 31d
when: always
@ -86,7 +92,7 @@
.rspec-metadata-pg-10: &rspec-metadata-pg-10
<<: *rspec-metadata
<<: *use-pg-10
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-golang-1.11-git-2.21-chrome-73.0-node-10.x-yarn-1.12-postgresql-10-graphicsmagick-1.3.29"
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.21-chrome-73.0-node-12.x-yarn-1.16-postgresql-10-graphicsmagick-1.3.29"
.rspec-metadata-mysql: &rspec-metadata-mysql
<<: *rspec-metadata
@ -105,15 +111,15 @@
variables:
SETUP_DB: "false"
script:
- git fetch https://gitlab.com/gitlab-org/gitlab-ce.git v11.5.0
- git fetch https://gitlab.com/gitlab-org/gitlab-ce.git v11.11.0
- git checkout -f FETCH_HEAD
- sed -i "s/gem 'oj', '~> 2.17.4'//" Gemfile
- bundle update google-protobuf grpc
- sed -i "s/gem 'bootsnap', '~> 1.0.0'/gem 'bootsnap'/" Gemfile
- bundle update google-protobuf grpc bootsnap
- 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
- bundle exec rake add_limits_mysql
- date
- git checkout -f $CI_COMMIT_SHA
- bundle install $BUNDLE_INSTALL_FLAGS
@ -140,19 +146,68 @@ setup-test-env:
except:
- /(^docs[\/-].*|.*-docs$)/
rspec-pg:
rspec unit pg:
<<: *rspec-metadata-pg
parallel: 50
parallel: 20
rspec-pg-10:
rspec integration pg:
<<: *rspec-metadata-pg
parallel: 6
rspec system pg:
<<: *rspec-metadata-pg
parallel: 24
rspec unit pg-10:
<<: *rspec-metadata-pg-10
<<: *only-schedules-master
parallel: 50
parallel: 20
rspec-mysql:
rspec integration pg-10:
<<: *rspec-metadata-pg-10
<<: *only-schedules-master
parallel: 6
rspec system pg-10:
<<: *rspec-metadata-pg-10
<<: *only-schedules-master
parallel: 24
rspec unit mysql:
<<: *rspec-metadata-mysql
<<: *only-schedules-master
parallel: 50
parallel: 20
rspec integration mysql:
<<: *rspec-metadata-mysql
<<: *only-schedules-master
parallel: 6
rspec system mysql:
<<: *rspec-metadata-mysql
<<: *only-schedules-master
parallel: 24
.rspec-mysql-on-demand: &rspec-mysql-on-demand
only:
variables:
- $CI_COMMIT_MESSAGE =~ /\[run mysql\]/i
- $CI_COMMIT_REF_NAME =~ /mysql/
rspec unit mysql on-demand:
<<: *rspec-metadata-mysql
<<: *rspec-mysql-on-demand
parallel: 20
rspec integration mysql on-demand:
<<: *rspec-metadata-mysql
<<: *rspec-mysql-on-demand
parallel: 6
rspec system mysql on-demand:
<<: *rspec-metadata-mysql
<<: *rspec-mysql-on-demand
parallel: 24
rspec-fast-spec-helper:
<<: *rspec-metadata-pg
@ -164,16 +219,17 @@ rspec-fast-spec-helper:
script:
- export CACHE_CLASSES=true
- scripts/gitaly-test-spawn
- bin/rspec --color --format documentation --tag quarantine spec/
- bin/rspec --color --format documentation --tag quarantine -- spec/
rspec-pg-quarantine:
rspec quarantine pg:
<<: *rspec-metadata-pg
<<: *rspec-quarantine
allow_failure: true
rspec-mysql-quarantine:
rspec quarantine mysql:
<<: *rspec-metadata-mysql
<<: *rspec-quarantine
<<: *only-schedules-master
allow_failure: true
static-analysis:
@ -184,7 +240,7 @@ static-analysis:
script:
- scripts/static-analysis
cache:
key: "debian-stretch-ruby-2.5.3-node-10.x-and-rubocop"
key: "debian-stretch-ruby-2.6.3-node-12.x-and-rubocop"
paths:
- vendor/ruby
- .yarn-cache/

View file

@ -54,7 +54,7 @@ build-qa-image:
- time docker push ${QA_IMAGE}
.review-build-cng-base: &review-build-cng-base
image: ruby:2.5-alpine
image: ruby:2.6-alpine
stage: test
when: manual
before_script:
@ -76,9 +76,8 @@ schedule:review-build-cng:
.review-deploy-base: &review-deploy-base
<<: *review-base
stage: review
retry: 2
allow_failure: true
stage: review
variables:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
@ -129,8 +128,8 @@ review-stop:
.review-qa-base: &review-qa-base
<<: *review-docker
stage: qa
allow_failure: true
stage: qa
variables:
<<: *review-docker-variables
QA_ARTIFACTS_DIR: "${CI_PROJECT_DIR}/qa"
@ -159,19 +158,22 @@ review-stop:
review-qa-smoke:
<<: *review-qa-base
retry: 2
script:
- gitlab-qa Test::Instance::Smoke "${QA_IMAGE}" "${CI_ENVIRONMENT_URL}"
review-qa-all:
<<: *review-qa-base
allow_failure: true
when: manual
parallel: 5
script:
- export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/review-qa-all_master_report.json
- export KNAPSACK_TEST_FILE_PATTERN=qa/specs/features/**/*_spec.rb
- gitlab-qa Test::Instance::Any "${QA_IMAGE}" "${CI_ENVIRONMENT_URL}"
.review-performance-base: &review-performance-base
<<: *review-qa-base
stage: qa
allow_failure: true
before_script:
- export CI_ENVIRONMENT_URL="$(cat review_app_url.txt)"
- echo "${CI_ENVIRONMENT_URL}"

View file

@ -40,12 +40,12 @@ update-tests-metadata:
policy: push
script:
- retry gem install fog-aws mime-types activesupport rspec_profiling postgres-copy --no-document
- scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec-pg_node_*.json
- scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec_*_pg_node_*.json
- '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH'
- rm -f knapsack/${CI_PROJECT_NAME}/*_node_*.json
- scripts/merge-reports ${FLAKY_RSPEC_SUITE_REPORT_PATH} rspec_flaky/all_*_*.json
- FLAKY_RSPEC_GENERATE_REPORT=1 scripts/prune-old-flaky-specs ${FLAKY_RSPEC_SUITE_REPORT_PATH}
- '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH'
- '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $FLAKY_RSPEC_SUITE_REPORT_PATH'
- rm -f knapsack/${CI_PROJECT_NAME}/*_node_*.json
- rm -f rspec_flaky/all_*.json rspec_flaky/new_*.json
- scripts/insert-rspec-profiling-data
only:
@ -56,7 +56,7 @@ update-tests-metadata:
flaky-examples-check:
extends: .dedicated-runner
image: ruby:2.5-alpine
image: ruby:2.6-alpine
services: []
before_script: []
variables:

View file

@ -0,0 +1,9 @@
# Yamllint of *.yml for .gitlab-ci.yml.
# This uses rules from project root `.yamllint`.
lint-ci-gitlab:
extends: .dedicated-runner
before_script: []
dependencies: []
image: sdesbure/yamllint:latest
script:
- yamllint .gitlab-ci.yml .gitlab/ci lib/gitlab/ci/templates

View file

@ -27,9 +27,9 @@ and verify the issue you're about to submit isn't a duplicate.
### Example Project
(If possible, please create an example project here on GitLab.com that exhibits the problematic behaviour, and link to it here in the bug report)
(If possible, please create an example project here on GitLab.com that exhibits the problematic behavior, and link to it here in the bug report)
(If you are using an older version of GitLab, this will also determine whether the bug has been fixed in a more recent version)
(If you are using an older version of GitLab, this will also determine whether the bug is fixed in a more recent version)
### What is the current *bug* behavior?
@ -42,7 +42,7 @@ and verify the issue you're about to submit isn't a duplicate.
### Relevant logs and/or screenshots
(Paste any relevant logs - please use code blocks (```) to format console output,
logs, and code as it's very hard to read otherwise.)
logs, and code as it's tough to read otherwise.)
### Output of checks

View file

@ -0,0 +1,43 @@
<!-- Title suggestion: [Feature flag] Enable description of feature -->
## What
Remove the `:feature_name` feature flag ...
## Owners
- Team: NAME_OF_TEAM
- Most appropriate slack channel to reach out to: `#g_TEAM_NAME`
- Best individual to reach out to: NAME
## Expectations
### What are we expecting to happen?
### What might happen if this goes wrong?
### What can we monitor to detect problems with this?
<!-- Which dashboards from https://dashboards.gitlab.net are most relevant? -->
## Beta groups/projects
If applicable, any groups/projects that are happy to have this feature turned on early. Some organizations may wish to test big changes they are interested in with a small subset of users ahead of time for example.
- `gitlab-org/gitlab-ce`/`gitlab-org/gitlab-ee` projects
- `gitlab-org`/`gitlab-com` groups
- ...
## Roll Out Steps
- [ ] Enable on staging
- [ ] Test on staging
- [ ] Ensure that documentation has been updated
- [ ] Enable on GitLab.com for individual groups/projects listed above and verify behaviour
- [ ] Announce on the issue an estimated time this will be enabled on GitLab.com
- [ ] Enable on GitLab.com by running chatops command in `#production`
- [ ] Cross post chatops slack command to `#support_gitlab-com` and in your team channel
- [ ] Announce on the issue that the flag has been enabled
- [ ] Remove feature flag and add changelog entry
/label ~"feature flag"

View file

@ -17,10 +17,10 @@ Set the title to: `Description of the original issue`
#### Backports
- [ ] Once the MR is ready to be merged, create MRs targetting the last 3 releases, plus the current RC if between the 7th and 22nd of the month.
- [ ] Once the MR is ready to be merged, create MRs targeting the last 3 releases, plus the current RC if between the 7th and 22nd of the month.
- [ ] At this point, it might be easy to squash the commits from the MR into one
- You can use the script `bin/secpick` instead of the following steps, to help you cherry-picking. See the [secpick documentation]
- [ ] Create each MR targetting the stable branch `X-Y-stable`, using the "Security Release" merge request template.
- [ ] Create each MR targeting the stable branch `X-Y-stable`, using the "Security Release" merge request template.
- Every merge request will have its own set of TODOs, so make sure to
complete those.
- [ ] Make sure all MRs have a link in the [links section](#links)

View file

@ -1,9 +1,13 @@
inherits_from:
- .haml-lint_todo.yml
# Whether to ignore frontmatter at the beginning of HAML documents for
# frameworks such as Jekyll/Middleman
skip_frontmatter: false
exclude:
- 'vendor/**/*'
- 'spec/**/*'
require:
- './haml_lint/linter/no_plain_nodes.rb'
linters:
AltText:

523
.haml-lint_todo.yml Normal file
View file

@ -0,0 +1,523 @@
# This configuration was generated by
# `haml-lint --auto-gen-config`
# on 2019-05-07 19:04:08 +0100 using Haml-Lint version 0.30.0.
# The point is for the user to remove these configuration records
# one by one as the lints are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of Haml-Lint, may require this file to be generated again.
linters:
# Offense count: 2075
NoPlainNodes:
enabled: true
exclude:
- "app/views/admin/abuse_reports/_abuse_report.html.haml"
- "app/views/admin/abuse_reports/index.html.haml"
- "app/views/admin/appearances/_form.html.haml"
- "app/views/admin/application_settings/_abuse.html.haml"
- "app/views/admin/application_settings/_diff_limits.html.haml"
- "app/views/admin/application_settings/_gitaly.html.haml"
- "app/views/admin/application_settings/_influx.html.haml"
- "app/views/admin/application_settings/_ip_limits.html.haml"
- "app/views/admin/application_settings/_logging.html.haml"
- "app/views/admin/application_settings/_performance.html.haml"
- "app/views/admin/application_settings/_plantuml.html.haml"
- "app/views/admin/application_settings/_prometheus.html.haml"
- "app/views/admin/application_settings/_realtime.html.haml"
- "app/views/admin/application_settings/_repository_check.html.haml"
- "app/views/admin/application_settings/_repository_storage.html.haml"
- "app/views/admin/application_settings/_signin.html.haml"
- "app/views/admin/application_settings/_signup.html.haml"
- "app/views/admin/application_settings/_spam.html.haml"
- "app/views/admin/application_settings/_terminal.html.haml"
- "app/views/admin/application_settings/_usage.html.haml"
- "app/views/admin/application_settings/_visibility_and_access.html.haml"
- "app/views/admin/applications/_delete_form.html.haml"
- "app/views/admin/applications/_form.html.haml"
- "app/views/admin/applications/edit.html.haml"
- "app/views/admin/applications/index.html.haml"
- "app/views/admin/applications/new.html.haml"
- "app/views/admin/applications/show.html.haml"
- "app/views/admin/background_jobs/show.html.haml"
- "app/views/admin/broadcast_messages/index.html.haml"
- "app/views/admin/dashboard/index.html.haml"
- "app/views/admin/deploy_keys/new.html.haml"
- "app/views/admin/groups/show.html.haml"
- "app/views/admin/health_check/show.html.haml"
- "app/views/admin/hook_logs/_index.html.haml"
- "app/views/admin/hook_logs/show.html.haml"
- "app/views/admin/hooks/_form.html.haml"
- "app/views/admin/hooks/edit.html.haml"
- "app/views/admin/hooks/index.html.haml"
- "app/views/admin/labels/_form.html.haml"
- "app/views/admin/logs/show.html.haml"
- "app/views/admin/projects/_projects.html.haml"
- "app/views/admin/projects/show.html.haml"
- "app/views/admin/requests_profiles/index.html.haml"
- "app/views/admin/runners/_runner.html.haml"
- "app/views/admin/runners/index.html.haml"
- "app/views/admin/runners/show.html.haml"
- "app/views/admin/services/_form.html.haml"
- "app/views/admin/services/index.html.haml"
- "app/views/admin/spam_logs/_spam_log.html.haml"
- "app/views/admin/spam_logs/index.html.haml"
- "app/views/admin/system_info/show.html.haml"
- "app/views/admin/users/_access_levels.html.haml"
- "app/views/admin/users/_form.html.haml"
- "app/views/admin/users/_head.html.haml"
- "app/views/admin/users/_profile.html.haml"
- "app/views/admin/users/_projects.html.haml"
- "app/views/admin/users/new.html.haml"
- "app/views/admin/users/projects.html.haml"
- "app/views/admin/users/show.html.haml"
- "app/views/clusters/clusters/_cluster.html.haml"
- "app/views/clusters/clusters/_form.html.haml"
- "app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml"
- "app/views/clusters/clusters/gcp/_form.html.haml"
- "app/views/clusters/clusters/new.html.haml"
- "app/views/dashboard/milestones/index.html.haml"
- "app/views/dashboard/projects/_blank_state_admin_welcome.html.haml"
- "app/views/dashboard/projects/_blank_state_welcome.html.haml"
- "app/views/dashboard/projects/_zero_authorized_projects.html.haml"
- "app/views/dashboard/snippets/index.html.haml"
- "app/views/dashboard/todos/_todo.html.haml"
- "app/views/dashboard/todos/index.html.haml"
- "app/views/devise/confirmations/almost_there.haml"
- "app/views/devise/mailer/_confirmation_instructions_account.html.haml"
- "app/views/devise/mailer/_confirmation_instructions_secondary.html.haml"
- "app/views/devise/mailer/email_changed.html.haml"
- "app/views/devise/mailer/password_change.html.haml"
- "app/views/devise/mailer/reset_password_instructions.html.haml"
- "app/views/devise/mailer/unlock_instructions.html.haml"
- "app/views/devise/passwords/edit.html.haml"
- "app/views/devise/sessions/_new_base.html.haml"
- "app/views/devise/sessions/_new_crowd.html.haml"
- "app/views/devise/sessions/_new_ldap.html.haml"
- "app/views/devise/sessions/new.html.haml"
- "app/views/devise/sessions/two_factor.html.haml"
- "app/views/devise/shared/_omniauth_box.html.haml"
- "app/views/devise/shared/_sign_in_link.html.haml"
- "app/views/devise/shared/_signup_box.html.haml"
- "app/views/devise/shared/_tabs_normal.html.haml"
- "app/views/discussions/_discussion.html.haml"
- "app/views/discussions/_headline.html.haml"
- "app/views/discussions/_notes.html.haml"
- "app/views/discussions/_resolve_all.html.haml"
- "app/views/doorkeeper/applications/_delete_form.html.haml"
- "app/views/doorkeeper/authorized_applications/_delete_form.html.haml"
- "app/views/errors/encoding.html.haml"
- "app/views/errors/git_not_found.html.haml"
- "app/views/errors/omniauth_error.html.haml"
- "app/views/errors/precondition_failed.html.haml"
- "app/views/events/_commit.html.haml"
- "app/views/events/_event_push.atom.haml"
- "app/views/events/event/_push.html.haml"
- "app/views/groups/_create_chat_team.html.haml"
- "app/views/groups/_group_admin_settings.html.haml"
- "app/views/groups/group_members/_new_group_member.html.haml"
- "app/views/groups/group_members/index.html.haml"
- "app/views/groups/labels/edit.html.haml"
- "app/views/groups/labels/new.html.haml"
- "app/views/groups/milestones/edit.html.haml"
- "app/views/groups/milestones/index.html.haml"
- "app/views/groups/milestones/new.html.haml"
- "app/views/groups/projects.html.haml"
- "app/views/groups/runners/edit.html.haml"
- "app/views/groups/settings/_advanced.html.haml"
- "app/views/groups/settings/_lfs.html.haml"
- "app/views/help/_shortcuts.html.haml"
- "app/views/help/index.html.haml"
- "app/views/help/instance_configuration.html.haml"
- "app/views/help/instance_configuration/_gitlab_ci.html.haml"
- "app/views/help/instance_configuration/_gitlab_pages.html.haml"
- "app/views/help/instance_configuration/_ssh_info.html.haml"
- "app/views/help/ui.html.haml"
- "app/views/import/bitbucket/status.html.haml"
- "app/views/import/bitbucket_server/status.html.haml"
- "app/views/instance_statistics/cohorts/_cohorts_table.html.haml"
- "app/views/instance_statistics/cohorts/_usage_ping.html.haml"
- "app/views/invites/show.html.haml"
- "app/views/layouts/_mailer.html.haml"
- "app/views/layouts/header/_default.html.haml"
- "app/views/layouts/header/_new_dropdown.haml"
- "app/views/layouts/mailer/devise.html.haml"
- "app/views/layouts/nav/sidebar/_profile.html.haml"
- "app/views/layouts/notify.html.haml"
- "app/views/notify/_failed_builds.html.haml"
- "app/views/notify/_reassigned_issuable_email.html.haml"
- "app/views/notify/_removal_notification.html.haml"
- "app/views/notify/autodevops_disabled_email.html.haml"
- "app/views/notify/changed_milestone_email.html.haml"
- "app/views/notify/import_issues_csv_email.html.haml"
- "app/views/notify/issue_moved_email.html.haml"
- "app/views/notify/member_access_denied_email.html.haml"
- "app/views/notify/member_invite_accepted_email.html.haml"
- "app/views/notify/member_invite_declined_email.html.haml"
- "app/views/notify/member_invited_email.html.haml"
- "app/views/notify/new_gpg_key_email.html.haml"
- "app/views/notify/new_mention_in_issue_email.html.haml"
- "app/views/notify/new_ssh_key_email.html.haml"
- "app/views/notify/new_user_email.html.haml"
- "app/views/notify/pages_domain_disabled_email.html.haml"
- "app/views/notify/pages_domain_enabled_email.html.haml"
- "app/views/notify/pages_domain_verification_failed_email.html.haml"
- "app/views/notify/pages_domain_verification_succeeded_email.html.haml"
- "app/views/notify/pipeline_failed_email.html.haml"
- "app/views/notify/pipeline_success_email.html.haml"
- "app/views/notify/project_was_exported_email.html.haml"
- "app/views/notify/project_was_moved_email.html.haml"
- "app/views/notify/project_was_not_exported_email.html.haml"
- "app/views/notify/push_to_merge_request_email.html.haml"
- "app/views/notify/remote_mirror_update_failed_email.html.haml"
- "app/views/notify/removed_milestone_issue_email.html.haml"
- "app/views/notify/removed_milestone_merge_request_email.html.haml"
- "app/views/notify/repository_push_email.html.haml"
- "app/views/peek/views/_gc.html.haml"
- "app/views/peek/views/_redis.html.haml"
- "app/views/peek/views/_sidekiq.html.haml"
- "app/views/profiles/_event_table.html.haml"
- "app/views/profiles/active_sessions/_active_session.html.haml"
- "app/views/profiles/active_sessions/index.html.haml"
- "app/views/profiles/audit_log.html.haml"
- "app/views/profiles/chat_names/_chat_name.html.haml"
- "app/views/profiles/chat_names/index.html.haml"
- "app/views/profiles/chat_names/new.html.haml"
- "app/views/profiles/emails/index.html.haml"
- "app/views/profiles/gpg_keys/_key.html.haml"
- "app/views/profiles/gpg_keys/index.html.haml"
- "app/views/profiles/keys/_key.html.haml"
- "app/views/profiles/keys/_key_details.html.haml"
- "app/views/profiles/keys/index.html.haml"
- "app/views/profiles/notifications/show.html.haml"
- "app/views/profiles/passwords/edit.html.haml"
- "app/views/profiles/personal_access_tokens/index.html.haml"
- "app/views/profiles/preferences/show.html.haml"
- "app/views/profiles/show.html.haml"
- "app/views/profiles/two_factor_auths/_codes.html.haml"
- "app/views/profiles/two_factor_auths/codes.html.haml"
- "app/views/profiles/two_factor_auths/create.html.haml"
- "app/views/profiles/two_factor_auths/show.html.haml"
- "app/views/projects/_bitbucket_import_modal.html.haml"
- "app/views/projects/_customize_workflow.html.haml"
- "app/views/projects/_deletion_failed.html.haml"
- "app/views/projects/_fork_suggestion.html.haml"
- "app/views/projects/_gitlab_import_modal.html.haml"
- "app/views/projects/_home_panel.html.haml"
- "app/views/projects/_import_project_pane.html.haml"
- "app/views/projects/_issuable_by_email.html.haml"
- "app/views/projects/_md_preview.html.haml"
- "app/views/projects/_new_project_fields.html.haml"
- "app/views/projects/_readme.html.haml"
- "app/views/projects/artifacts/_tree_file.html.haml"
- "app/views/projects/artifacts/browse.html.haml"
- "app/views/projects/blame/_age_map_legend.html.haml"
- "app/views/projects/blame/show.html.haml"
- "app/views/projects/blob/_editor.html.haml"
- "app/views/projects/blob/_header_content.html.haml"
- "app/views/projects/blob/_new_dir.html.haml"
- "app/views/projects/blob/_remove.html.haml"
- "app/views/projects/blob/_render_error.html.haml"
- "app/views/projects/blob/_template_selectors.html.haml"
- "app/views/projects/blob/_upload.html.haml"
- "app/views/projects/blob/edit.html.haml"
- "app/views/projects/blob/new.html.haml"
- "app/views/projects/blob/preview.html.haml"
- "app/views/projects/blob/viewers/_empty.html.haml"
- "app/views/projects/blob/viewers/_stl.html.haml"
- "app/views/projects/branches/_branch.html.haml"
- "app/views/projects/branches/_commit.html.haml"
- "app/views/projects/branches/_delete_protected_modal.html.haml"
- "app/views/projects/branches/new.html.haml"
- "app/views/projects/ci/builds/_build.html.haml"
- "app/views/projects/ci/lints/_create.html.haml"
- "app/views/projects/commit/_change.html.haml"
- "app/views/projects/commits/_commit.html.haml"
- "app/views/projects/commits/_inline_commit.html.haml"
- "app/views/projects/compare/_form.html.haml"
- "app/views/projects/compare/index.html.haml"
- "app/views/projects/cycle_analytics/_empty_stage.html.haml"
- "app/views/projects/cycle_analytics/_no_access.html.haml"
- "app/views/projects/cycle_analytics/_overview.html.haml"
- "app/views/projects/cycle_analytics/show.html.haml"
- "app/views/projects/deploy_keys/_form.html.haml"
- "app/views/projects/deploy_keys/_index.html.haml"
- "app/views/projects/deploy_keys/edit.html.haml"
- "app/views/projects/deploy_tokens/_revoke_modal.html.haml"
- "app/views/projects/deploy_tokens/_table.html.haml"
- "app/views/projects/deployments/_deployment.html.haml"
- "app/views/projects/diffs/_file_header.html.haml"
- "app/views/projects/diffs/_replaced_image_diff.html.haml"
- "app/views/projects/diffs/_stats.html.haml"
- "app/views/projects/empty.html.haml"
- "app/views/projects/environments/show.html.haml"
- "app/views/projects/forks/error.html.haml"
- "app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml"
- "app/views/projects/graphs/charts.html.haml"
- "app/views/projects/hook_logs/_index.html.haml"
- "app/views/projects/hook_logs/show.html.haml"
- "app/views/projects/hooks/_index.html.haml"
- "app/views/projects/hooks/edit.html.haml"
- "app/views/projects/imports/new.html.haml"
- "app/views/projects/imports/show.html.haml"
- "app/views/projects/issues/_issue.html.haml"
- "app/views/projects/issues/_new_branch.html.haml"
- "app/views/projects/issues/import_csv/_modal.html.haml"
- "app/views/projects/issues/show.html.haml"
- "app/views/projects/jobs/_header.html.haml"
- "app/views/projects/jobs/_table.html.haml"
- "app/views/projects/jobs/index.html.haml"
- "app/views/projects/labels/edit.html.haml"
- "app/views/projects/labels/new.html.haml"
- "app/views/projects/mattermosts/_no_teams.html.haml"
- "app/views/projects/mattermosts/_team_selection.html.haml"
- "app/views/projects/mattermosts/new.html.haml"
- "app/views/projects/merge_requests/_commits.html.haml"
- "app/views/projects/merge_requests/_discussion.html.haml"
- "app/views/projects/merge_requests/_how_to_merge.html.haml"
- "app/views/projects/merge_requests/_merge_request.html.haml"
- "app/views/projects/merge_requests/_mr_title.html.haml"
- "app/views/projects/merge_requests/conflicts/_commit_stats.html.haml"
- "app/views/projects/merge_requests/conflicts/_file_actions.html.haml"
- "app/views/projects/merge_requests/conflicts/_submit_form.html.haml"
- "app/views/projects/merge_requests/conflicts/components/_diff_file_editor.html.haml"
- "app/views/projects/merge_requests/conflicts/components/_inline_conflict_lines.html.haml"
- "app/views/projects/merge_requests/conflicts/show.html.haml"
- "app/views/projects/merge_requests/creations/_diffs.html.haml"
- "app/views/projects/merge_requests/creations/_new_compare.html.haml"
- "app/views/projects/merge_requests/creations/_new_submit.html.haml"
- "app/views/projects/merge_requests/diffs/_different_base.html.haml"
- "app/views/projects/merge_requests/diffs/_diffs.html.haml"
- "app/views/projects/merge_requests/diffs/_version_controls.html.haml"
- "app/views/projects/merge_requests/invalid.html.haml"
- "app/views/projects/merge_requests/widget/open/_error.html.haml"
- "app/views/projects/mirrors/_regenerate_public_ssh_key_confirm_modal.html.haml"
- "app/views/projects/mirrors/_ssh_host_keys.html.haml"
- "app/views/projects/new.html.haml"
- "app/views/projects/no_repo.html.haml"
- "app/views/projects/pages/_access.html.haml"
- "app/views/projects/pages/_destroy.haml"
- "app/views/projects/pages/_https_only.html.haml"
- "app/views/projects/pages/_list.html.haml"
- "app/views/projects/pages/_no_domains.html.haml"
- "app/views/projects/pages/_use.html.haml"
- "app/views/projects/pages/show.html.haml"
- "app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml"
- "app/views/projects/pipelines/_info.html.haml"
- "app/views/projects/pipelines/charts/_pipelines.haml"
- "app/views/projects/protected_branches/shared/_branches_list.html.haml"
- "app/views/projects/protected_branches/shared/_create_protected_branch.html.haml"
- "app/views/projects/protected_branches/shared/_dropdown.html.haml"
- "app/views/projects/protected_branches/shared/_index.html.haml"
- "app/views/projects/protected_branches/shared/_matching_branch.html.haml"
- "app/views/projects/protected_branches/shared/_protected_branch.html.haml"
- "app/views/projects/protected_branches/show.html.haml"
- "app/views/projects/protected_tags/shared/_create_protected_tag.html.haml"
- "app/views/projects/protected_tags/shared/_dropdown.html.haml"
- "app/views/projects/protected_tags/shared/_index.html.haml"
- "app/views/projects/protected_tags/shared/_matching_tag.html.haml"
- "app/views/projects/protected_tags/shared/_protected_tag.html.haml"
- "app/views/projects/protected_tags/shared/_tags_list.html.haml"
- "app/views/projects/protected_tags/show.html.haml"
- "app/views/projects/registry/repositories/_tag.html.haml"
- "app/views/projects/repositories/_feed.html.haml"
- "app/views/projects/runners/_shared_runners.html.haml"
- "app/views/projects/runners/edit.html.haml"
- "app/views/projects/services/_form.html.haml"
- "app/views/projects/services/_index.html.haml"
- "app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml"
- "app/views/projects/services/mattermost_slash_commands/_help.html.haml"
- "app/views/projects/services/prometheus/_metrics.html.haml"
- "app/views/projects/services/slack_slash_commands/_help.html.haml"
- "app/views/projects/settings/ci_cd/_badge.html.haml"
- "app/views/projects/settings/ci_cd/_form.html.haml"
- "app/views/projects/stage/_stage.html.haml"
- "app/views/projects/tags/index.html.haml"
- "app/views/projects/tags/new.html.haml"
- "app/views/projects/tags/releases/edit.html.haml"
- "app/views/projects/tree/_tree_row.html.haml"
- "app/views/projects/tree/_truncated_notice_tree_row.html.haml"
- "app/views/projects/triggers/_content.html.haml"
- "app/views/projects/triggers/_form.html.haml"
- "app/views/projects/triggers/_index.html.haml"
- "app/views/projects/triggers/_trigger.html.haml"
- "app/views/projects/triggers/edit.html.haml"
- "app/views/projects/wikis/_new.html.haml"
- "app/views/projects/wikis/_pages_wiki_page.html.haml"
- "app/views/projects/wikis/edit.html.haml"
- "app/views/projects/wikis/history.html.haml"
- "app/views/repository_check_mailer/notify.html.haml"
- "app/views/search/_form.html.haml"
- "app/views/search/results/_issue.html.haml"
- "app/views/search/results/_note.html.haml"
- "app/views/search/results/_snippet_blob.html.haml"
- "app/views/search/results/_snippet_title.html.haml"
- "app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml"
- "app/views/shared/_commit_message_container.html.haml"
- "app/views/shared/_confirm_modal.html.haml"
- "app/views/shared/_delete_label_modal.html.haml"
- "app/views/shared/_group_form.html.haml"
- "app/views/shared/_group_tips.html.haml"
- "app/views/shared/_milestone_expired.html.haml"
- "app/views/shared/_no_password.html.haml"
- "app/views/shared/_no_ssh.html.haml"
- "app/views/shared/_outdated_browser.html.haml"
- "app/views/shared/_personal_access_tokens_created_container.html.haml"
- "app/views/shared/_personal_access_tokens_table.html.haml"
- "app/views/shared/_ping_consent.html.haml"
- "app/views/shared/_project_limit.html.haml"
- "app/views/shared/_service_settings.html.haml"
- "app/views/shared/boards/components/_board.html.haml"
- "app/views/shared/boards/components/_sidebar.html.haml"
- "app/views/shared/boards/components/sidebar/_due_date.html.haml"
- "app/views/shared/boards/components/sidebar/_labels.html.haml"
- "app/views/shared/boards/components/sidebar/_milestone.html.haml"
- "app/views/shared/empty_states/_priority_labels.html.haml"
- "app/views/shared/hook_logs/_content.html.haml"
- "app/views/shared/issuable/_assignees.html.haml"
- "app/views/shared/issuable/_board_create_list_dropdown.html.haml"
- "app/views/shared/issuable/_bulk_update_sidebar.html.haml"
- "app/views/shared/issuable/_close_reopen_report_toggle.html.haml"
- "app/views/shared/issuable/_form.html.haml"
- "app/views/shared/issuable/_search_bar.html.haml"
- "app/views/shared/issuable/_sidebar.html.haml"
- "app/views/shared/issuable/form/_default_templates.html.haml"
- "app/views/shared/issuable/form/_issue_assignee.html.haml"
- "app/views/shared/issuable/form/_template_selector.html.haml"
- "app/views/shared/issuable/form/_title.html.haml"
- "app/views/shared/labels/_form.html.haml"
- "app/views/shared/members/_member.html.haml"
- "app/views/shared/milestones/_form_dates.html.haml"
- "app/views/shared/milestones/_issuable.html.haml"
- "app/views/shared/milestones/_milestone.html.haml"
- "app/views/shared/milestones/_sidebar.html.haml"
- "app/views/shared/milestones/_top.html.haml"
- "app/views/shared/notes/_hints.html.haml"
- "app/views/shared/notes/_note.html.haml"
- "app/views/shared/notifications/_button.html.haml"
- "app/views/shared/notifications/_custom_notifications.html.haml"
- "app/views/shared/notifications/_new_button.html.haml"
- "app/views/shared/notifications/_notification_dropdown.html.haml"
- "app/views/shared/plugins/_index.html.haml"
- "app/views/shared/projects/_dropdown.html.haml"
- "app/views/shared/projects/_list.html.haml"
- "app/views/shared/projects/_project.html.haml"
- "app/views/shared/runners/_runner_description.html.haml"
- "app/views/shared/runners/show.html.haml"
- "app/views/shared/snippets/_embed.html.haml"
- "app/views/shared/snippets/_header.html.haml"
- "app/views/shared/snippets/_snippet.html.haml"
- "app/views/shared/tokens/_scopes_list.html.haml"
- "app/views/shared/web_hooks/_form.html.haml"
- "app/views/shared/web_hooks/_test_button.html.haml"
- "app/views/u2f/_authenticate.html.haml"
- "app/views/u2f/_register.html.haml"
- "app/views/users/_deletion_guidance.html.haml"
- "ee/app/views/admin/_namespace_plan_info.html.haml"
- "ee/app/views/admin/application_settings/_elasticsearch_form.html.haml"
- "ee/app/views/admin/application_settings/_slack.html.haml"
- "ee/app/views/admin/application_settings/_snowplow.html.haml"
- "ee/app/views/admin/application_settings/_templates.html.haml"
- "ee/app/views/admin/audit_logs/index.html.haml"
- "ee/app/views/admin/dashboard/stats.html.haml"
- "ee/app/views/admin/emails/show.html.haml"
- "ee/app/views/admin/geo/nodes/edit.html.haml"
- "ee/app/views/admin/geo/nodes/new.html.haml"
- "ee/app/views/admin/geo/projects/_registry_failed.html.haml"
- "ee/app/views/admin/geo/projects/_registry_never.html.haml"
- "ee/app/views/admin/licenses/_breakdown.html.haml"
- "ee/app/views/admin/licenses/_upload_trial_license.html.haml"
- "ee/app/views/admin/licenses/missing.html.haml"
- "ee/app/views/admin/licenses/new.html.haml"
- "ee/app/views/admin/licenses/show.html.haml"
- "ee/app/views/admin/monitoring/ee/_nav.html.haml"
- "ee/app/views/admin/projects/_shared_runner_status.html.haml"
- "ee/app/views/admin/push_rules/show.html.haml"
- "ee/app/views/admin/users/_limits.html.haml"
- "ee/app/views/admin/users/_user_detail_note.html.haml"
- "ee/app/views/dashboard/projects/_blank_state_ee_trial.html.haml"
- "ee/app/views/errors/kerberos_denied.html.haml"
- "ee/app/views/groups/analytics/show.html.haml"
- "ee/app/views/groups/audit_events/index.html.haml"
- "ee/app/views/groups/ee/_settings_nav.html.haml"
- "ee/app/views/groups/epics/_epic.html.haml"
- "ee/app/views/groups/group_members/_ldap_sync.html.haml"
- "ee/app/views/groups/group_members/_sync_button.html.haml"
- "ee/app/views/groups/hooks/_project_hook.html.haml"
- "ee/app/views/groups/hooks/index.html.haml"
- "ee/app/views/groups/ldap_group_links/index.html.haml"
- "ee/app/views/groups/pipeline_quota/index.html.haml"
- "ee/app/views/jira_connect/subscriptions/index.html.haml"
- "ee/app/views/layouts/jira_connect.html.haml"
- "ee/app/views/layouts/nav/ee/_epic_link.html.haml"
- "ee/app/views/layouts/nav/ee/admin/_new_monitoring_sidebar.html.haml"
- "ee/app/views/layouts/service_desk.html.haml"
- "ee/app/views/ldap_group_links/_form.html.haml"
- "ee/app/views/ldap_group_links/_ldap_group_link.html.haml"
- "ee/app/views/ldap_group_links/_ldap_group_links.html.haml"
- "ee/app/views/ldap_group_links/_ldap_group_links_show.html.haml"
- "ee/app/views/ldap_group_links/_ldap_group_links_synchronizations.html.haml"
- "ee/app/views/namespaces/_shared_runner_status.html.haml"
- "ee/app/views/namespaces/_shared_runners_minutes_setting.html.haml"
- "ee/app/views/namespaces/pipelines_quota/_extra_shared_runners_minutes_quota.html.haml"
- "ee/app/views/namespaces/pipelines_quota/_list.haml"
- "ee/app/views/notify/approved_merge_request_email.html.haml"
- "ee/app/views/notify/epic_status_changed_email.html.haml"
- "ee/app/views/notify/issues_csv_email.html.haml"
- "ee/app/views/notify/new_review_email.html.haml"
- "ee/app/views/notify/prometheus_alert_fired_email.html.haml"
- "ee/app/views/notify/send_admin_notification.html.haml"
- "ee/app/views/notify/send_unsubscribed_notification.html.haml"
- "ee/app/views/notify/unapproved_merge_request_email.html.haml"
- "ee/app/views/oauth/geo_auth/error.html.haml"
- "ee/app/views/profiles/pipeline_quota/index.haml"
- "ee/app/views/projects/audit_events/index.html.haml"
- "ee/app/views/projects/blob/_owners.html.haml"
- "ee/app/views/projects/commits/_mirror_status.html.haml"
- "ee/app/views/projects/feature_flags/_configure_feature_flags_modal.html.haml"
- "ee/app/views/projects/issues/_issue_weight.html.haml"
- "ee/app/views/projects/issues/_related_issues.html.haml"
- "ee/app/views/projects/issues/export_csv/_modal.html.haml"
- "ee/app/views/projects/jobs/_shared_runner_limit_warning.html.haml"
- "ee/app/views/projects/merge_requests/_approvals_count.html.haml"
- "ee/app/views/projects/merge_requests/widget/open/_geo.html.haml"
- "ee/app/views/projects/mirrors/_mirrored_repositories_count.html.haml"
- "ee/app/views/projects/protected_branches/ee/_create_protected_branch.html.haml"
- "ee/app/views/projects/protected_branches/ee/_dropdown.html.haml"
- "ee/app/views/projects/protected_branches/ee/_fallback_update_protected_branch.html.haml"
- "ee/app/views/projects/protected_tags/_protected_tag_extra_create_access_levels.haml"
- "ee/app/views/projects/protected_tags/ee/_create_protected_tag.html.haml"
- "ee/app/views/projects/push_rules/_index.html.haml"
- "ee/app/views/projects/services/gitlab_slack_application/_help.html.haml"
- "ee/app/views/projects/services/gitlab_slack_application/_slack_integration_form.html.haml"
- "ee/app/views/projects/services/prometheus/_metrics.html.haml"
- "ee/app/views/projects/settings/slacks/edit.html.haml"
- "ee/app/views/shared/_additional_email_text.html.haml"
- "ee/app/views/shared/_geo_info_modal.html.haml"
- "ee/app/views/shared/_mirror_update_button.html.haml"
- "ee/app/views/shared/_shared_runners_minutes_limit.html.haml"
- "ee/app/views/shared/audit_events/_event_table.html.haml"
- "ee/app/views/shared/boards/components/_list_weight.html.haml"
- "ee/app/views/shared/boards/components/sidebar/_epic.html.haml"
- "ee/app/views/shared/ee/_import_form.html.haml"
- "ee/app/views/shared/epic/_search_bar.html.haml"
- "ee/app/views/shared/issuable/_approvals.html.haml"
- "ee/app/views/shared/issuable/_board_create_list_dropdown.html.haml"
- "ee/app/views/shared/issuable/_filter_weight.html.haml"
- "ee/app/views/shared/issuable/_sidebar_item_epic.haml"
- "ee/app/views/shared/members/ee/_ldap_tag.html.haml"
- "ee/app/views/shared/members/ee/_override_member_buttons.html.haml"
- "ee/app/views/shared/members/ee/_sso_badge.html.haml"
- "ee/app/views/shared/milestones/_burndown.html.haml"
- "ee/app/views/shared/milestones/_weight.html.haml"
- "ee/app/views/shared/promotions/_promote_audit_events.html.haml"
- "ee/app/views/shared/promotions/_promote_burndown_charts.html.haml"
- "ee/app/views/shared/promotions/_promote_csv_export.html.haml"
- "ee/app/views/shared/promotions/_promote_issue_weights.html.haml"
- "ee/app/views/shared/promotions/_promote_repository_features.html.haml"
- "ee/app/views/shared/promotions/_promote_servicedesk.html.haml"
- "ee/app/views/shared/push_rules/_form.html.haml"
- "ee/app/views/unsubscribes/show.html.haml"
- "ee/app/views/admin/users/_auditor_access_level_radio.html.haml"
- "ee/app/views/admin/users/_auditor_user_badge.html.haml"
- "ee/app/views/projects/protected_branches/_update_protected_branch.html.haml"

2
.nvmrc
View file

@ -1 +1 @@
10.13.0
12.4.0

View file

@ -799,7 +799,6 @@ Style/SelfAssignment:
Exclude:
- 'app/models/concerns/bulk_member_access_load.rb'
- 'app/serializers/base_serializer.rb'
- 'spec/features/projects/clusters/interchangeability_spec.rb'
- 'spec/support/import_export/configuration_helper.rb'
# Offense count: 50

View file

@ -1 +1 @@
2.5.3
2.6.3

7
.yamllint Normal file
View file

@ -0,0 +1,7 @@
---
extends: default
rules:
line-length: disable
document-start: disable

View file

@ -2,15 +2,50 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 11.11.8
## 12.0.8
### Security (22 changes)
- Ensure only authorised users can create notes on Merge Requests and Issues.
- Add :login_recaptcha_protection_enabled setting to prevent bots from brute-force attacks.
- Queries for Upload should be scoped by model.
- Speed up regexp in namespace format by failing fast after reaching maximum namespace depth.
- Limit the size of issuable description and comments.
- Send TODOs for comments on commits correctly.
- Restrict MergeRequests#test_reports to authenticated users with read-access on Builds.
- Added image proxy to mitigate potential stealing of IP addresses.
- Filter out old system notes for epics in notes api endpoint response.
- Avoid exposing unaccessible repo data upon GFM post processing.
- Fix HTML injection for label description.
- Make sure HTML text is always escaped when replacing label/milestone references.
- Prevent DNS rebind on JIRA service integration.
- Use admin_group authorization in Groups::RunnersController.
- Prevent disclosure of merge request ID via email.
- Show cross-referenced MR-id in issues' activities only to authorized users.
- Enforce max chars and max render time in markdown math.
- Check permissions before responding in MergeController#pipeline_status.
- Remove EXIF from users/personal snippet uploads.
- Fix project import restricted visibility bypass via API.
- Fix weak session management by clearing password reset tokens after login (username/email) are updated.
- Fix SSRF via DNS rebinding in Kubernetes Integration.
## 12.0.7
- Unreleased due to QA failure.
## 12.0.6
### Security (2 changes)
- Upgrade Gitaly to 1.42.7 to prevent revision flag injection exploits.
- Upgrade pages to 1.5.1 to prevent gitlab api token recovery from cookie.
- Upgrade Gitaly to 1.47.2 to prevent revision flag injection exploits.
- Upgrade pages to 1.6.2 to prevent gitlab api token recovery from cookie.
## 12.0.5
## 11.11.7
- No changes.
## 12.0.4
### Security (9 changes)
@ -25,33 +60,352 @@ entry.
- Drop feature to take ownership of trigger token.
## 11.11.6
- Unreleased due to QA failure.
## 11.11.5 (2019-06-27)
## 12.0.3 (2019-06-27)
- No changes.
### Security (10 changes)
- Disable Rails SQL query cache when applying service templates. !30060
- Add missing authorizations in GraphQL.
- Persist tmp snippet uploads at users.
- Gate MR head_pipeline behind read_pipeline ability.
- Fix DoS vulnerability in color validation regex.
- Expose merge requests count based on user access.
- Fix Denial of Service for comments when rendering issues/MR comments.
- Gate MR head_pipeline behind read_pipeline ability.
- Add missing authorizations in GraphQL.
- Disable Rails SQL query cache when applying service templates.
- Prevent Billion Laughs attack.
- Correctly check permissions when creating snippet notes.
- Prevent the detection of merge request templates by unauthorized users.
- Persist tmp snippet uploads at users.
## 11.11.4 (2019-06-26)
## 12.0.2 (2019-06-25)
### Fixed (3 changes)
### Fixed (7 changes, 1 of them is from the community)
- Fix missing API notification flags for Microsoft Teams. !29824 (Seiji Suenaga)
- Fixed 'diff version changes' link not working. !29825
- Fix label serialization in issue and note hooks. !29850
- Include the GitLab version in the cache key for Gitlab::JsonCache. !29938
- Prevent EE backport migrations from running if CE is not migrated. !30002
- Silence backup warnings when CRON=1 in use. !30033
- Fix comment emails not respecting group-level notification email.
### Performance (1 change)
- Omit issues links in merge request entity API response. !29917
## 12.0.1 (2019-06-24)
- No changes.
## 12.0.0 (2019-06-22)
### Security (10 changes)
- Hide confidential issue title on unsubscribe for anonymous users.
- Fix url redaction for issue links.
- Fix confidential issue label disclosure on milestone view.
- Filter relative links in wiki for XSS.
- Prevent XSS injection in note imports.
- Resolve: Milestones leaked via search API.
- Prevent bypass of restriction disabling web password sign in.
- Add extra fields for handling basic auth on import by url page.
- Protect Gitlab::HTTP against DNS rebinding attack.
- Prevent invalid branch for merge request.
### Removed (5 changes, 1 of them is from the community)
- Remove ability for group clusters to be automatically configured on creation. !27245
- Removes support for AUTO_DEVOPS_DOMAIN. !28460
- Remove the circuit breaker API. !28669
- Make Kubernetes service templates readonly. !29044
- Remove Content-Type override for Mattermost OAuth login. (Harrison Healey)
### Fixed (116 changes, 28 of them are from the community)
- Fix col-sm-* in forms to keep layout. !24885 (Takuya Noguchi)
- Avoid 500 when rendering users ATOM data. !25408
- Fix flyout nav on small viewports. !25998
- Fix proxy support in Container Scanning. !27246
- preventing blocked users and their PipelineSchdules from creating new Pipelines. !27318
- Fix yaml linting for GitLab CI inside project (.gitlab/ci) *.yml files and CI template files. !27576 (Will Hall)
- Fix yaml linting for project root *.yml files. !27579 (Will Hall)
- Added a content field to atom feed. !27652
- Bring secondary button styles up to design standard. !27920
- Use FindOrCreateService to create labels and check for existing ones. !27987 (Matt Duren)
- Fix "too many loops" error by handling gracefully cron schedules for non existent days. !28002
- Handle errors in successful notes reply. !28082
- Fix 500 error when accessing charts with an anonymous user. !28091 (Diego Silva)
- Allow user to set primary email first when 2FA is required. !28097 (Kartikey Tanna)
- Auto-DevOps: allow to disable rollout status check. !28130 (Sergej Nikolaev <kinolaev@gmail.com>)
- Resolved JIRA service: NoMethodError: undefined method 'find' for nil:NilClass. !28206
- Supports Matomo/Piwik string website ID ("Protect Track ID" plugin). !28214 (DUVERGIER Claude)
- Fix loading.. dropdown at search field. !28275 (Pavel Chausov)
- Remove unintended error message shown when moving issues. !28317
- Properly clear the merge error upon rebase failure. !28319
- Upgrade dependencies for node 12 compatibility. !28323
- Fix. `db:migrate` is failed on MySQL 8. !28351 (sue445)
- Fix an error in projects admin when statistics are missing. !28355
- Fix emojis URLs. !28371
- Prevent common name collisions when requesting multiple Let's Encrypt certificates concurrently. !28373
- Fix issue that causes "Save changes" button in project settings pages to be enabled/disabled incorrectly when changes are made to the form. !28377
- Fix diff notes and discussion notes being exported as regular notes. !28401
- Fix padding in MR widget. !28472
- Updates loading icon in commits page. !28475
- Fix border radius of discussions. !28490
- Update broadcast message action icons. !28496 (Jarek Ostrowski @jareko)
- Update icon color to match design system, pass accessibility. !28498 (Jarek Ostrowski @jareko)
- Show data on Cycle Analytics page when value is less than a second. !28507
- Fix dropdown position when loading remote data. !28526
- Delete unauthorized Todos when project is made private. !28560
- Change links in system notes to use relative paths. !28588 (Luke Picciau)
- Update favicon from next. !28601 (Jarek Ostrowski @jareko)
- Open visibility help link in a new tab. !28603 (George Tsiolis)
- Fix issue importing members with owner access. !28636
- Fix the height of the page headers on issues/merge request/snippets pages. !28650 (Erik van der Gaag)
- Always show "Pipelines must succeed" checkbox. !28651
- Resolve moving an issue results in broken image links in comments. !28654
- Fix milestone references containing &, <, or >. !28667
- Add hover and focus to Attach a file. !28682
- Correctly word-wrapping project descriptions with very long words. !28695 (Erik van der Gaag)
- Prevent icons from shrinking in User popover when contents exceed container. !28696
- Allow removal of empty lines via suggestions. !28703
- Throw an error when formatDate's input is invalid. !28713
- Fix order dependency with user params during imports. !28719
- Fix search dropdown not closing on blur if empty. !28730
- Fixed ignored postgres version that occurs after the first autodevops deploy when specifying custom $POSTGRES_VERSION. !28735 (Brandon Dimcheff)
- Limit milestone dates to before year 9999. !28742 (Luke Picciau)
- Set project default visibility to max allowed. !28754
- Cancel auto merge when merge request is closed. !28782
- Fixes Ref link being displayed as raw HTML in the Pipelines page. !28823
- Fix job name in graph dropdown overflowing. !28824
- Add style to disable webkit icons for search inputs. !28833 (Jarek Ostrowski @jareko)
- Fix email notifications for user excluded actions. !28835
- Resolve Tooltip Consistency. !28839
- Fix Merge Request merge checkbox alignment on mobile view. !28845
- Add referenced-commands in no overflow list. !28858
- Fix participants list wrapping. !28873
- Excludes MR author from Review roulette. !28886 (Jacopo Beschi @jacopo-beschi)
- Give labels consistent weight. !28895
- Added padding to time window dropdown in monitor dashboard. !28897
- Move text under p tag. !28901
- Resolve Position is off when visiting files with anchors. !28913
- Fix whitespace changes visibility when the related file was initially collapsed. !28950 (Ondřej Budai)
- Fix emoji picker visibility issue. !28984
- Resolve Merge request discussion text jumps when resolved. !28995
- Allow lowercase prefix for Youtrack issue ids. !29057 (Matthias Baur)
- Add support to view entirety of long branch name in dropdown instead of it being cut off. !29069
- Fix inconsistent option dropdown button height to match adjacent button. !29096
- Improve new user email markup unconsistency between text and html parts. !29111 (Haunui Saint-sevin)
- Eliminate color inconsistencies in metric graphs. !29127
- Avoid setting Gitlab::Session on sessionless requests and Git HTTP. !29146
- Use the selected time window for metrics dashboard. !29152
- Remove build policies from serverless app template. !29253
- Fix serverless apps deployments by bumping 'tm' version. !29254
- Include the port in the URLs of the API Link headers. !29267
- Fix Fogbugz Importer not working. !29383
- Fix GPG signature verification with recent GnuPG versions. !29388 (David Palubin)
- Cancel Auto Merge when target branch is changed. !29416
- Fix nil coercion updating storage size on project statistics. !29425
- Ignore legacy artifact columns in Project Import/Export. !29427
- Avoid DB timeouts when scheduling migrations. !29437
- Handle encoding errors for MergeToRefService. !29440
- Fix UTF-8 conversion issues when resolving conflicts. !29453
- Enlarge metrics time-window dropdown links. !29458
- Remove unnecessary decimals on Metrics chart axis. !29468
- Fix scrolling to top on assignee change. !29500
- Allow command/control click to open link in new tab on Merge Request tabs. !29506
- Omit blocked admins from repository check e-mails. !29507
- Fix diverged branch locals. !29508
- Process up to 100 commit messages for references when pushing to a new default branch. !29511 (Fabio Papa)
- Allow developer role to delete docker tags via container registry API. !29512
- Fix "Resolve conflicts" button not appearing for some users. !29535
- Fix: propagate all documented ENV vars to CI when using SAST. !29564
- AutoDevops function ensure_namespace() now explicitly tests the namespace. !29567 (Jack Lei)
- Fix sidebar flyout navigation. !29571
- Fix missing deployment rockets in monitor dashboard. !29574
- Fix inability to set visibility_level on project via API. !29578
- Ensure a Kubernetes namespace is not used for deployments if there is no service account token associated with it. !29643
- Refresh service_account_token for kubernetes_namespaces. !29657
- Expose all current events properly on services API. !29736 (Zsolt Kovari)
- Move Dropdown to Stick to MR View App Button. !29767
- Fix IDE commit using latest ref in branch and overriding contents. !29769
- Revert concurrent pipeline creation for pipeline schedules. !29794
- Fix layout of group milestone header.
- Fix remote mirrors not updating after tag push.
- Fix padding of unclickable pipeline dropdown items to match links.
- Change resolve button text to mark comment as resolved.
- Align system note within discussion with other notes.
- Fix border radii on diff files and repo files.
- Fixed show whitespace button not refetching diff content.
- Fix pipeline schedules when owner is nil.
### Changed (35 changes, 13 of them are from the community)
- Include information if issue was clossed via merge request or commit. !15610 (Michał Zając)
- Removes duplicated members from api/projects/:id/members/all. !24005 (Jacopo Beschi @jacopo-beschi)
- Apply the group setting "require 2FA" across all subgroup members as well when changing the group setting. !24965 (rroger)
- Enable function features for external Knative installations. !27173
- Remove dind from DAST template. !28083
- Update registration form to indicate invalid name or username length on input. !28095 (Jiaan Louw)
- Default masked to false for new variables. !28186
- Better isolated `Docker.gitlab-ci.yml` to avoid interference with other job configurations. !28213 (lrkwz)
- Remove the mr_push_options feature flag. !28278
- Replace Oxygen-Sans font with Noto Sans. !28322
- Update new smiley icons, find n replace old names with new ones. !28338 (Jarek Ostrowski)
- Adds a text label to color pickers to improve accessibility. !28343 (Chris Toynbee)
- Prioritize login form on mobile breakpoint. !28360
- Move some project routes under /-/ scope. !28435
- I18n for issue closure reason in emails. !28489 (Michał Zając)
- Geo: Remove Gitlab::LfsToken::LegacyRedisDeviseToken implementation and usage. !28546
- Add check circle filled icon for resolved comments. !28663
- Update project security dashboard documentation. !28681
- Remove `docker pull` prefix when copying a tag from the registry. !28757 (Benedikt Franke)
- Adjust milestone completion rate to be based on issues count. !28777
- Enhance line-height of Activity feed UI. !28856 (Jacopo Beschi @jacopo-beschi)
- Upgrade to Gitaly v1.43.0. !28867
- Do not display Update app button when saving Knative domain name. !28904
- Rebrush of flash-warning according to the new design (brighter background and darker font). !28916 (Michel Engelen)
- Added reference, web_path, and relative_position fields to GraphQL Issue. !28998
- Change logic behind cycle analytics. !29018
- Add documentation links for confidental and locked discussions. !29073
- Update GITALY_SERVER_VERSION to 1.45.0. !29109
- Allow masking if 8 or more characters in base64. !29143 (thomas-nilsson-irfu)
- Replaces sidekiq mtail metrics with ruby instrumentation metrics. !29215
- Allow references to labels and milestones to contain emoji. !29284
- changed the styles on `Add List` dropdown to look more like the EE vesion. !29338 (Michel Engelen)
- Hashed Storage is enabled by default on new installations. !29586
- Upgrade to Gitaly v1.47.0. !29789
- Default MR checkbox to true in most cases.
### Performance (11 changes)
- Improve performance of jobs controller. !28093
- Upgrade Ruby version to 2.6.3. !28117
- Make pipeline schedule worker resilient. !28407
- Fix performance issue with large Markdown content in issue or merge request description. !28597
- Improve clone performance by using delta islands. !28871
- Reduce Gitaly calls to improve performance when rendering suggestions. !29027
- Use Redis for CacheMarkDownField on non AR models. !29054
- Add index on public_email for users. !29430
- Speed up commit loads by disabling BatchLoader replace_methods. !29633
- Add index on invite_email for members. !29768
- Improve performance of users autocomplete when there are lots of results.
### Added (47 changes, 12 of them are from the community)
- Added option to filter jobs by age in the /job/request API endpoint. !1340 (Dmitry Chepurovskiy)
- Add ability to define notification email addresses for groups you belong to. !25299
- Add wiki size to project statistics. !25321 (Peter Marko)
- 58404 - setup max depth for GraphQL. !25737 (Ken Ding)
- Add auto SSL toggle option to Pages domain settings page. !26438
- Empty project state for Web IDE. !26556
- Add support for multiple job parents in GitLab CI YAML. !26801 (Wolphin (Nikita))
- Pass user's identity and token from JupyterHub to user's Jupyter environment. !27314 (Amit Rathi)
- Add issues_statistics api endpoints and extend issues search api. !27366
- Validate Kubernetes credentials at cluster creation. !27403
- Update the merge request widget's "Merge" button to support merge trains. !27594
- Style the toast component according to design specs. !27734
- Add API support for committing changes to different projects in same fork network. !27915
- Add support for && and || to CI Pipeline Expressions. Change CI variable expression matching for Lexeme::Pattern to eagerly return tokens. !27925 (Martin Manelli)
- Added ref querystring parameter to project search API to allow searching on branches/tags other than the default. !28069 (Lee Tickett)
- Add notify_only_default_branch option to PipelinesEmailService. !28271 (Peter Marko)
- Support multiplex GraphQL queries. !28273
- Add Namespace and ProjectStatistics to GraphQL API. !28277
- Display classname JUnit attribute in report modal. !28376
- API: Allow to get and set "masked" attribute for variables. !28381 (Mathieu Parent)
- Add allow_failure attribute to Job API. !28406
- Add support for AsciiDoc include directive. !28417 (Jakub Jirutka & Guillaume Grossetie)
- Migrate Kubernetes service integration templates to clusters. !28534
- Allow issue list to be sorted by relative order. !28566
- Implement borderless discussion design with new reply field. !28580
- Add expand/collapse to error tracking settings. !28619
- Adds collapsible sections for job log. !28642
- Add LFS oid to GraphQL blob type. !28666
- Allow users to specify a time range on metrics dashboard. !28670
- Add a New Copy Button That Works in Modals. !28676
- Add Kubernetes logs to Admin Logs UI. !28685
- Set up git client in Jupyter installtion. !28783 (Amit Rathi)
- Add task count and completed count to responses of Issue and MR. !28859
- Add project level git depth CI/CD setting. !28919
- Use global IDs when exposing GraphQL resources. !29080
- Expose wiki_size on GraphQL API. !29123
- Expose notes and discussions in GraphQL. !29212
- Use to 'gitlabktl' build serverless applications. !29258
- Adds pagination component for graphql api. !29277
- Allow switching clusters between managed and unmanaged. !29322
- Get and edit ci_default_git_depth via project API. !29353
- Link to an external dashboard from metrics dashboard. !29369
- Add labels to note event payload. !29384 (Sujay Patel)
- Add Join meeting button to issues with Zoom links. !29454
- Make task completion status available via GraphQL.
- Add backtraces to Peek performance bar for SQL calls.
- Added diff suggestion feature discovery popover.
### Other (62 changes, 14 of them are from the community)
- Unified EE/CS differences in repository/show.html. !13562
- Remove legacy artifact related code. !26475
- Backport the EE schema and migrations to CE. !26940 (Yorick Peterse)
- Add dedicated logging for GraphQL queries. !27885
- i18n: externalize strings from user profile settings. !28088 (Antony Liu)
- Omit max-count for diverging_commit_counts behind feature flag. !28157
- Fix alignment of resend button in members page. !28202
- Update indirect dependency fsevents from 1.2.4 to 1.2.9. !28220 (Takuya Noguchi)
- Update get_process_mem to 0.2.3. !28248
- Add Pool repository to the usage ping. !28267
- Forbid NULL in project_statistics.packages_size. !28400
- Update Gitaly to v1.42.1. !28425
- Upgrade babel to 7.4.4. !28437 (Takuya Noguchi)
- Externalize profiles preferences. !28470 (George Tsiolis)
- Update GitLab Runner Helm Chart to 0.5.0. !28497
- Change collapse icon size to size of profile picture. !28512
- Resolve Snippet icon button is misaligned. !28522
- Bumps Kubernetes in Auto DevOps to 1.11.10. !28525
- Bump Helm version in Auto-DevOps.gitlab-ci.yml to 2.14.0. !28527
- Migrate the monitoring dashboard store to vuex. !28555
- Give New Snippet button green outline. !28559
- Removes project_auto_devops#domain column. !28574
- Externalize strings of email page in user profile. !28587 (antony liu)
- Externalize strings of active sessions page in user profile. !28590 (antony liu)
- Refactor and abstract Auto Merge Processes. !28595
- Add section to dev docs on accessing chatops. !28623
- Externalize strings of chat page in user profile. !28632
- Externalize strings of PGP Keys and SSH Keys page in user profile. !28653 (Antony Liu)
- Added the `.extended-height` class to the labels-dropdown. !28659 (Michel Engelen)
- Moved EE/CE code differences for `app/assets/javascripts/gl_dropdown.js` into CE. !28711 (Michel Engelen)
- Update GitLab Runner Helm Chart to 0.5.1. !28720
- Remove support for using Geo with an installation from source. !28737
- API: change masked attribute type to Boolean. !28758
- API: change protected attribute type to Boolean. !28766
- Add a column header to admin/jobs page. !28837
- Reset merge status from mergeable MRs. !28843
- Show tooltip on truncated commit title. !28865 (Timofey Trofimov)
- Added conditional rendering to `app/views/search/_form.html.haml` for CE/EE code base consistency. !28883 (Michel Engelen)
- Change "Report abuse to GitLab" to more generic wording. !28884 (Marc Schwede)
- Update GitLab Pages to v1.6.0. !29048
- Update GitLab Runner Helm Chart to 0.5.2. !29050
- User link styling for commits. !29150
- Fix null source_project_id in pool_repositories. !29157
- Add deletion protection setting column to application_settings table. !29268
- Added code differnces from EE in file 'app/assets/javascripts/pages/projects/project.js' to CE. !29271 (Michel Engelen)
- Update to GitLab Shell v9.3.0. !29283
- Document when milestones and labels links are missing. !29355
- Make margin between buttons consistent. !29378
- Changed the 'Created' label to 'Last Updated' on the container registry table to more accurately reflect what the date represents. !29464
- Update GitLab Pages to v1.6.1. !29559
- Indent collapsible sections. !29804
- Group download buttons into a .btn-group.
- Change default color of award emoji button.
- Use blue for activity stream links; use monospace font for commit sha.
- Remove fixed height from MR diff headers.
- Moves the table pagination shared component.
- Add warning that gitlab-secrets isn't included in backup.
- Update merge request tabs so they no longer scroll.
- Reduce height of issue board input to align with buttons.
- Increase height of move issue dropdown.
- Use grid and correct border radius for status badge.
- Moves snowplow to CE repo.
## 11.11.3 (2019-06-10)
@ -82,24 +436,6 @@ entry.
- Fix input group height.
## 11.11.1 (2019-05-30)
### Security (12 changes)
- Add DNS rebinding protection settings.
- Prevent XSS injection in note imports.
- Prevent invalid branch for merge request.
- Filter relative links in wiki for XSS.
- Fix confidential issue label disclosure on milestone view.
- Fix url redaction for issue links.
- Resolve: Milestones leaked via search API.
- Protect Gitlab::HTTP against DNS rebinding attack.
- Add extra fields for handling basic auth on import by url page.
- Prevent bypass of restriction disabling web password sign in.
- Update Gitaly to fix GetArchive vulnerability.
- Hide confidential issue title on unsubscribe for anonymous users.
## 11.11.0 (2019-05-22)
### Security (1 change)
@ -285,6 +621,23 @@ entry.
- Add some frozen string to spec/**/*.rb. (gfyoung)
## 11.10.6 (2019-06-04)
### Fixed (7 changes, 1 of them is from the community)
- Allow a member to have an access level equal to parent group. !27913
- Fix uploading of LFS tracked file through UI. !28052
- Use 3-way merge for squashing commits. !28078
- Use a path for the related merge requests endpoint. !28171
- Fix project visibility level validation. !28305 (Peter Marko)
- Fix Rugged get_tree_entries recursive flag not working. !28494
- Use source ref in pipeline webhook. !28772
### Other (1 change)
- Fix input group height.
## 11.10.4 (2019-05-01)
### Fixed (12 changes)
@ -576,6 +929,24 @@ entry.
- Removes EE differences for environment_item.vue.
## 11.9.12 (2019-05-30)
### Security (12 changes, 1 of them is from the community)
- Protect Gitlab::HTTP against DNS rebinding attack.
- Fix project visibility level validation. (Peter Marko)
- Update Knative version.
- Add DNS rebinding protection settings.
- Prevent XSS injection in note imports.
- Prevent invalid branch for merge request.
- Filter relative links in wiki for XSS.
- Fix confidential issue label disclosure on milestone view.
- Fix url redaction for issue links.
- Resolve: Milestones leaked via search API.
- Prevent bypass of restriction disabling web password sign in.
- Hide confidential issue title on unsubscribe for anonymous users.
## 11.9.10 (2019-04-26)
### Security (5 changes)
@ -695,7 +1066,7 @@ entry.
- Forbid creating discussions for users with restricted access.
- Fix leaking private repository information in API.
- Fixed ability to see private groups by users not belonging to given group.
- Prevent releases links API to leak tag existance.
- Prevent releases links API to leak tag existence.
- Display the correct number of MRs a user has access to.
- Block local URLs for Kubernetes integration.
- Fix arbitrary file read via diffs during import.
@ -1054,7 +1425,7 @@ entry.
- Display SAML failure messages instead of expecting CSRF token. !24509
- Adjust vertical alignment for project visibility icons. !24511 (Martin Hobert)
- Load initUserInternalRegexPlaceholder only when required. !24522
- Hashed Storage: `AfterRenameService` was receiving the wrong `old_path` under some circunstances. !24526
- Hashed Storage: `AfterRenameService` was receiving the wrong `old_path` under some circumstances. !24526
- Resolve Runners IPv6 address overlaps other values. !24531
- Fix 404s with snippet uploads in object storage. !24550
- Fixed oversized custom project notification selector dropdown. !24557
@ -1093,7 +1464,7 @@ entry.
- Update CI YAML param table with include.
- Return bottom border on MR Tabs.
- Fixes z-index and margins of archived alert in job page.
- Fixes archived sticky top bar without perfomance bar.
- Fixes archived sticky top bar without performance bar.
- Fixed rebase button not showing in merge request widget.
- Fixed double tooltips on note awards buttons.
- Allow suggestions to be copied and pasted as GFM.
@ -1526,7 +1897,7 @@ entry.
- Fix deprecation: Using positional arguments in integration tests. !24009 (Jasper Maes)
- UI improvements for redesigned project lists. !24011
- Update cert-manager chart from v0.5.0 to v0.5.2. !24025 (Takuya Noguchi)
- Hide spinner on empty activites list on user profile overview. !24063
- Hide spinner on empty activities list on user profile overview. !24063
- Don't show Auto DevOps enabled banner for projects with CI file or CI disabled. !24067
- Update GitLab Runner Helm Chart to 0.1.43. !24083
- Fix navigation style in docs. !24090 (Takuya Noguchi)
@ -2055,7 +2426,7 @@ entry.
- Hide all tables on Pipeline when no Jobs for the Pipeline. !18540 (Takuya Noguchi)
- Fixing count on Milestones. !21446
- Use case insensitve username lookups. !21728 (William George)
- Use case insensitive username lookups. !21728 (William George)
- Correctly process Bamboo API result array. !21970 (Alex Lossent)
- Fix 'merged with' UI being displayed when merge request has no merge commit. !22022
- Fix broken file name navigation on MRs. !22109
@ -2838,7 +3209,7 @@ entry.
- Fixes SVGs for empty states in job page overflowing on mobile.
- Fix checkboxes on runner admin settings - The labels are now clickable.
- Fixed IDE file row scrolling into view when hovering.
- Accept upload files in public/uplaods/tmp when using accelerated uploads.
- Accept upload files in public/uploads/tmp when using accelerated uploads.
- Include correct CSS file for xterm in environments page.
- Increase padding in code blocks.
- Fix: Project deletion may not log audit events during user deletion.
@ -3724,7 +4095,7 @@ entry.
### Fixed (69 changes, 23 of them are from the community)
- Optimize the upload migration proces. !15947
- Optimize the upload migration process. !15947
- Import bitbucket issues that are reported by an anonymous user. !18199 (bartl)
- Fix an issue where the notification email address would be set to an unconfirmed email address. !18474
- Stop logging email information when emails are disabled. !18521 (Marc Shaw)
@ -3852,7 +4223,7 @@ entry.
- Add a cronworker to rescue stale live traces. !18680
- Move SquashBeforeMerge vue component. !18813 (George Tsiolis)
- Add index on runner_type for ci_runners. !18897
- Fix CarrierWave reads local files into memoery when migrates to ObjectStorage. !19102
- Fix CarrierWave reads local files into memory when migrates to ObjectStorage. !19102
- Remove double-checked internal id generation. !19181
- Throttle updates to Project#last_repository_updated_at. !19183
- Add background migrations for archiving legacy job traces. !19194
@ -3943,7 +4314,7 @@ entry.
- Adjust SQL and transaction Prometheus buckets.
- Adding branches through the WebUI is handled by Gitaly.
- Remove shellout implementation for Repository checksums.
- Refs containting sha checks are done by Gitaly.
- Refs containing sha checks are done by Gitaly.
- Finding a wiki page is done by Gitaly by default.
- Workhorse will use Gitaly to create archives.
- Workhorse to send raw diff and patch for commits.
@ -4147,7 +4518,7 @@ entry.
- Display active sessions and allow the user to revoke any of it. !17867 (Alexis Reigel)
- Add cron job to email users on issue due date. !17985 (Stuart Nelson)
- Rubocop rule to avoid returning from a block. !18000 (Jacopo Beschi @jacopo-beschi)
- Add the signature verfication badge to the compare view. !18245 (Marc Shaw)
- Add the signature verification badge to the compare view. !18245 (Marc Shaw)
- Expose Deploy Token data as environment varialbes on CI/CD jobs. !18414
- Show group id in group settings. !18482 (George Tsiolis)
- Allow admins to enforce accepting Terms of Service on an instance. !18570
@ -4885,7 +5256,7 @@ entry.
- Override group sidebar links. !16942 (George Tsiolis)
- Avoid running `PopulateForkNetworksRange`-migration multiple times. !16988
- Resolve PrepareUntrackedUploads PostgreSQL syntax error. !17019
- Fix monaco editor features which were incompatable with GitLab CDN settings. !17021
- Fix monaco editor features which were incompatible with GitLab CDN settings. !17021
- Fixed error 500 when removing an identity with synced attributes and visiting the profile page. !17054
- Fix cnacel edit note button reverting changes. !42462
- For issues display time of last edit of title or description instead of time of any attribute change.
@ -5102,7 +5473,7 @@ entry.
### Performance (2 changes)
- rework indexes on redirect_routes.
- Remove unecessary query from labels filter.
- Remove unnecessary query from labels filter.
## 10.4.0 (2018-01-22)
@ -5233,7 +5604,7 @@ entry.
- Add a gitlab:tcp_check rake task. !15759
- add support for sorting in tags api. !15772 (haseebeqx)
- Add Prometheus to available Cluster applications. !15895
- Validate file status when commiting multiple files. !15922
- Validate file status when committing multiple files. !15922
- List of avatars should never show +1. !15972 (Jacopo Beschi @jacopo-beschi)
- Do not generate NPM links for private NPM modules in blob view. !16002 (Mario de la Ossa)
- Backport fast database lookup of SSH authorized_keys from EE. !16014
@ -5264,7 +5635,7 @@ entry.
- Fix web ide user preferences copy and buttons. !41789
- Update redis-rack to 2.0.4.
- Import some code and functionality from gitlab-shell to improve subprocess handling.
- Update Browse file to Choose file in all occurences.
- Update Browse file to Choose file in all occurrences.
- Bump mysql2 gem version from 0.4.5 to 0.4.10. (asaparov)
- Use a background migration for issues.closed_at.
@ -5399,7 +5770,7 @@ entry.
- Fix graph notes number duplication. !15696 (Vladislav Kaverin)
- Fix updateEndpoint undefined error for issue_show app root. !15698
- Change boards page boards_data absolute urls to paths. !15703
- Using appropiate services in the API for managing forks. !15709
- Using appropriate services in the API for managing forks. !15709
- Confirming email with invalid token should no longer generate an error. !15726
- fix #39233 - 500 in merge request. !15774 (Martin Nowak)
- Use Markdown styling for new project guidelines. !15785 (Markus Koller)
@ -5509,7 +5880,7 @@ entry.
- Stop reloading the page when using pagination and tabs - use API calls - in Pipelines table.
- Clean up schema of the "issues" table.
- Clarify wording of protected branch settings for the default branch.
- Update svg external depencency.
- Update svg external dependency.
- Clean up schema of the "merge_requests" table.
@ -5679,7 +6050,7 @@ entry.
- Fix gitlab:backup rake for hashed storage based repositories. !15400
- Fix issue where clicking a GPG verification badge would scroll to the top of the page. !15407
- Update container repository path reference and allow using double underscore. !15417
- Fix crash when navigating to second page of the group dashbaord when there are projects and groups on the first page. !15456
- Fix crash when navigating to second page of the group dashboard when there are projects and groups on the first page. !15456
- Fix flash errors showing up on a non configured prometheus integration. !35652
- Fix timezone bug in Pikaday and upgrade Pikaday version.
- Fix arguments Import/Export error importing project merge requests.
@ -6229,7 +6600,7 @@ entry.
- [CHANGED] Fire hooks asynchronously when creating a new job to improve performance. !13734
- [CHANGED] Improve performance for AutocompleteController#users.json. !13754 (Hiroyuki Sato)
- [CHANGED] Update the GPG verification semantics: A GPG signature must additionally match the committer in order to be verified. !13771 (Alexis Reigel)
- [CHANGED] Support a multi-word fuzzy seach issues/merge requests on search bar. !13780 (Hiroyuki Sato)
- [CHANGED] Support a multi-word fuzzy search issues/merge requests on search bar. !13780 (Hiroyuki Sato)
- [CHANGED] Default LDAP config "verify_certificates" to true for security. !13915
- [CHANGED] "Share with group lock" now applies to subgroups, but owner can override setting on subgroups. !13944
- [CHANGED] Make Gitaly PostUploadPack mandatory. !13953
@ -6928,7 +7299,7 @@ entry.
## 9.3.2 (2017-06-27)
- API: Fix optional arugments for POST :id/variables. !12474
- API: Fix optional arguments for POST :id/variables. !12474
- Bump premailer-rails gem to 1.9.7 and its dependencies to prevent network retrieval of assets.
## 9.3.1 (2017-06-26)
@ -6945,7 +7316,7 @@ entry.
- Refactored gitlab:app:check into SystemCheck liberary and improve some checks. !9173
- Add an ability to cancel attaching file and redesign attaching files UI. !9431 (blackst0ne)
- Add Aliyun OSS as the backup storage provider. !9721 (Yuanfei Zhu)
- Add suport for find_local_branches GRPC from Gitaly. !10059
- Add support for find_local_branches GRPC from Gitaly. !10059
- Allow manual bypass of auto_sign_in_with_provider with a new param. !10187 (Maxime Besson)
- Redirect to user's keys index instead of user's index after a key is deleted in the admin. !10227 (Cyril Jouve)
- Changed Blame to Annotate in the UI to promote blameless culture. !10378 (Ilya Vassilevsky)
@ -7024,7 +7395,7 @@ entry.
- Add tag_list param to project api. !11799 (Ivan Chernov)
- Add changelog for improved Registry description. !11816
- Automatically adjust project settings to match changes in project visibility. !11831
- Add slugify project path to CI enviroment variables. !11838 (Ivan Chernov)
- Add slugify project path to CI environment variables. !11838 (Ivan Chernov)
- Add all pipeline sources as special keywords to 'only' and 'except'. !11844 (Filip Krakowski)
- Allow pulling of container images using personal access tokens. !11845
- Expose import_status in Projects API. !11851 (Robin Bobbitt)
@ -7939,7 +8310,7 @@ entry.
- Clean-up Project navigation order. !9272
- Add Runner's jobs v4 API. !9273
- Add pipeline trigger API with user permissions. !9277
- Enhanced filter issues layout for better mobile experiance. !9280 (Pratik Borsadiya)
- Enhanced filter issues layout for better mobile experience. !9280 (Pratik Borsadiya)
- Move babel config for instanbul to karma config. !9286 (winniehell)
- Document U2F limitations with multiple URLs. !9300
- Wrap long Project and Group titles. !9301
@ -8120,7 +8491,7 @@ entry.
- Add badges to global dropdown.
- Changed coverage reg expression placeholder text to be more like a placeholder.
- Show members of parent groups on project members page.
- Fix grammer issue in admin/runners.
- Fix grammar issue in admin/runners.
- Allow slashes in slash command arguments.
- Adds paginationd and folders view to environments table.
- hide loading spinners for server-rendered sidebar fields.
@ -8293,7 +8664,7 @@ entry.
- Allows to search within project by commit hash. (YarNayar)
- Show organisation membership and delete comment on smaller viewports, plus change comment author name to username.
- Remove turbolinks.
- Convert pipeline action icons to svg to have them propperly positioned.
- Convert pipeline action icons to svg to have them properly positioned.
- Remove rogue scrollbars for issue comments with inline elements.
- Align Segoe UI label text.
- Color + and - signs in diffs to increase code legibility.
@ -8584,3 +8955,4 @@ entry.
## 8.15.8 through 0.8.0
- See [changelogs/archive.md](changelogs/archive.md)

View file

@ -18,11 +18,11 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._
## Contributing Documentation has been moved
As of July 2018, all the documentation for contributing to the GitLab project has been moved to a new location.
[View the new documentation](doc/development/contributing/index.md) to find the latest information.
[View the new documentation](https://about.gitlab.com/community/contribute/) to find the latest information.
## Contribute to GitLab
This [documentation](doc/development/contributing/index.md#contribute-to-gitlab) has been moved.
[View the new documentation](https://about.gitlab.com/community/contribute/) to find the latest information.
## Security vulnerability disclosure
@ -42,7 +42,7 @@ This [documentation](doc/development/contributing/index.md#helping-others) has b
## I want to contribute!
This [documentation](doc/development/contributing/index.md#i-want-to-contribute) has been moved.
[View the new documentation](https://about.gitlab.com/community/contribute/) to find the latest information.
## Contribution Flow

View file

@ -1,5 +1,6 @@
# frozen_string_literal: true
danger.import_plugin('danger/plugins/helper.rb')
danger.import_plugin('danger/plugins/roulette.rb')
unless helper.release_automation?
danger.import_dangerfile(path: 'danger/metadata')

View file

@ -1 +1 @@
1.42.7
1.47.3

View file

@ -0,0 +1 @@
1.2.0

View file

@ -1 +1 @@
1.5.1
1.6.2

View file

@ -1 +1 @@
9.1.0
9.3.0

View file

@ -1 +1 @@
8.7.0
8.7.1

32
Gemfile
View file

@ -23,7 +23,7 @@ gem 'grape-path-helpers', '~> 1.1'
gem 'faraday', '~> 0.12'
# Authentication libraries
gem 'devise', '~> 4.4'
gem 'devise', '~> 4.6'
gem 'doorkeeper', '~> 4.3'
gem 'doorkeeper-openid_connect', '~> 1.5'
gem 'omniauth', '~> 1.8'
@ -41,7 +41,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.0'
gem 'omniauth_openid_connect', '~> 0.3.1'
gem "omniauth-ultraauth", '~> 0.0.2'
gem 'omniauth-salesforce', '~> 1.0.5'
gem 'rack-oauth2', '~> 1.9.3'
@ -60,6 +60,8 @@ gem 'u2f', '~> 0.2.1'
# GitLab Pages
gem 'validates_hostname', '~> 1.0.6'
gem 'rubyzip', '~> 1.2.2', require: 'zip'
# GitLab Pages letsencrypt support
gem 'acme-client', '~> 2.0.2'
# Browser detection
gem 'browser', '~> 2.5'
@ -128,6 +130,7 @@ gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 1.5.8'
gem 'asciidoctor-include-ext', '~> 0.3.1', require: false
gem 'asciidoctor-plantuml', '0.0.8'
gem 'rouge', '~> 3.1'
gem 'truncato', '~> 0.7.11'
@ -152,6 +155,7 @@ end
group :puma do
gem 'puma', '~> 3.12', require: false
gem 'puma_worker_killer', require: false
gem 'rack-timeout', require: false
end
# State machine
@ -167,7 +171,7 @@ gem 'redis-namespace', '~> 1.6.0'
gem 'gitlab-sidekiq-fetcher', '~> 0.4.0', require: 'sidekiq-reliable-fetch'
# Cron Parser
gem 'fugit', '~> 1.1'
gem 'fugit', '~> 1.2.1'
# HTTP requests
gem 'httparty', '~> 0.16.4'
@ -272,12 +276,12 @@ gem 'virtus', '~> 1.0.1'
gem 'base32', '~> 0.3.0'
# Sentry integration
gem 'sentry-raven', '~> 2.7'
gem 'sentry-raven', '~> 2.9'
gem 'premailer-rails', '~> 1.9.7'
# LabKit: Tracing and Correlation
gem 'gitlab-labkit', '~> 0.2.0'
gem 'gitlab-labkit', '~> 0.3.0'
# I18n
gem 'ruby_parser', '~> 3.8', require: false
@ -344,22 +348,22 @@ group :development, :test do
# Generate Fake data
gem 'ffaker', '~> 2.10'
gem 'capybara', '~> 2.18.0'
gem 'capybara', '~> 3.22.0'
gem 'capybara-screenshot', '~> 1.0.22'
gem 'selenium-webdriver', '~> 3.141'
gem 'spring', '~> 2.0.0'
gem 'spring-commands-rspec', '~> 1.0.4'
gem 'gitlab-styles', '~> 2.6', require: false
gem 'gitlab-styles', '~> 2.7', require: false
# Pin these dependencies, otherwise a new rule could break the CI pipelines
gem 'rubocop', '~> 0.68.1'
gem 'rubocop', '~> 0.69.0'
gem 'rubocop-performance', '~> 1.1.0'
gem 'rubocop-rspec', '~> 1.22.1'
gem 'scss_lint', '~> 0.56.0', require: false
gem 'haml_lint', '~> 0.30.0', require: false
gem 'simplecov', '~> 0.14.0', require: false
gem 'haml_lint', '~> 0.31.0', require: false
gem 'simplecov', '~> 0.16.1', require: false
gem 'bundler-audit', '~> 0.5.0', require: false
gem 'benchmark-ips', '~> 2.3.0', require: false
@ -370,6 +374,7 @@ group :development, :test do
gem 'activerecord_sane_schema_dumper', '1.0'
gem 'stackprof', '~> 0.2.10', require: false
gem 'derailed_benchmarks', require: false
gem 'simple_po_parser', '~> 1.1.2', require: false
@ -377,7 +382,7 @@ group :development, :test do
end
group :test do
gem 'shoulda-matchers', '~> 3.1.2', require: false
gem 'shoulda-matchers', '~> 4.0.1', require: false
gem 'email_spec', '~> 2.2.0'
gem 'json-schema', '~> 2.8.0'
gem 'webmock', '~> 3.5.1'
@ -397,6 +402,9 @@ gem 'html2text'
gem 'ruby-prof', '~> 0.17.0'
gem 'rbtrace', '~> 0.4', require: false
gem 'memory_profiler', '~> 0.9', require: false
gem 'benchmark-memory', '~> 0.1', require: false
gem 'activerecord-explain-analyze', '~> 0.1', require: false
# OAuth
gem 'oauth2', '~> 1.4'
@ -419,7 +427,7 @@ group :ed25519 do
end
# Gitaly GRPC client
gem 'gitaly-proto', '~> 1.27.2', require: 'gitaly'
gem 'gitaly-proto', '~> 1.32.0', require: 'gitaly'
gem 'grpc', '~> 1.19.0'

View file

@ -4,6 +4,8 @@ GEM
RedCloth (4.3.2)
abstract_type (0.0.7)
ace-rails-ap (4.1.2)
acme-client (2.0.2)
faraday (~> 0.9, >= 0.9.1)
actioncable (5.1.7)
actionpack (= 5.1.7)
nio4r (~> 2.0)
@ -36,6 +38,9 @@ GEM
activemodel (= 5.1.7)
activesupport (= 5.1.7)
arel (~> 8.0)
activerecord-explain-analyze (0.1.0)
activerecord (>= 4)
pg
activerecord_sane_schema_dumper (1.0)
rails (>= 5, < 6)
activesupport (5.1.7)
@ -62,6 +67,8 @@ GEM
faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.0)
asciidoctor (1.5.8)
asciidoctor-include-ext (0.3.1)
asciidoctor (>= 1.5.6, < 3.0.0)
asciidoctor-plantuml (0.0.8)
asciidoctor (~> 1.5)
ast (2.4.0)
@ -80,12 +87,14 @@ GEM
bcrypt (3.1.12)
bcrypt_pbkdf (1.0.0)
benchmark-ips (2.3.0)
benchmark-memory (0.1.2)
memory_profiler (~> 0.9)
better_errors (2.5.0)
coderay (>= 1.0.0)
erubi (>= 1.0.0)
rack (>= 0.9.0)
bindata (2.4.3)
binding_ninja (0.2.2)
binding_ninja (0.2.3)
binding_of_caller (0.8.0)
debug_inspector (>= 0.0.1)
bootsnap (1.4.1)
@ -103,13 +112,14 @@ GEM
bundler (~> 1.2)
thor (~> 0.18)
byebug (9.1.0)
capybara (2.18.0)
capybara (3.22.0)
addressable
mini_mime (>= 0.1.3)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (>= 2.0, < 4.0)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (~> 1.5)
xpath (~> 3.2)
capybara-screenshot (1.0.22)
capybara (>= 1.0, < 4)
launchy
@ -135,9 +145,9 @@ GEM
concord (0.1.5)
adamantium (~> 0.2.0)
equalizer (~> 0.0.9)
concurrent-ruby (1.1.3)
concurrent-ruby-ext (1.1.3)
concurrent-ruby (= 1.1.3)
concurrent-ruby (1.1.5)
concurrent-ruby-ext (1.1.5)
concurrent-ruby (= 1.1.5)
connection_pool (2.2.2)
crack (0.4.3)
safe_yaml (~> 1.0.0)
@ -153,10 +163,18 @@ GEM
html-pipeline
declarative (0.0.10)
declarative-option (0.1.0)
derailed_benchmarks (1.3.5)
benchmark-ips (~> 2)
get_process_mem (~> 0)
heapy (~> 0)
memory_profiler (~> 0)
rack (>= 1)
rake (> 10, < 13)
thor (~> 0.19)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
device_detector (1.0.0)
devise (4.4.3)
devise (4.6.2)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0, < 6.0)
@ -172,7 +190,7 @@ GEM
diffy (3.1.0)
discordrb-webhooks-blackst0ne (3.3.0)
rest-client (~> 2.0)
docile (1.1.5)
docile (1.3.1)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
doorkeeper (4.3.2)
@ -190,7 +208,7 @@ GEM
equalizer (0.0.11)
erubi (1.8.0)
escape_utils (1.2.1)
et-orbi (1.1.7)
et-orbi (1.2.1)
tzinfo
eventmachine (1.2.7)
excon (0.62.0)
@ -264,15 +282,15 @@ GEM
foreman (0.84.0)
thor (~> 0.19.1)
formatador (0.2.5)
fugit (1.1.9)
et-orbi (~> 1.1, >= 1.1.7)
fugit (1.2.1)
et-orbi (~> 1.1, >= 1.1.8)
raabro (~> 1.1)
fuubar (2.2.0)
rspec-core (~> 3.0)
ruby-progressbar (~> 1.4)
gemojione (3.3.0)
json
get_process_mem (0.2.0)
get_process_mem (0.2.3)
gettext (3.2.9)
locale (>= 2.0.5)
text (>= 1.3.0)
@ -283,22 +301,22 @@ GEM
gettext_i18n_rails (>= 0.7.1)
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
gitaly-proto (1.27.2)
gitaly-proto (1.32.0)
grpc (~> 1.0)
github-markup (1.7.0)
gitlab-default_value_for (3.1.1)
activerecord (>= 3.2.0, < 6.0)
gitlab-labkit (0.2.0)
gitlab-labkit (0.3.0)
actionpack (~> 5)
activesupport (~> 5)
grpc (~> 1.15)
grpc (~> 1.19.0)
jaeger-client (~> 0.10)
opentracing (~> 0.4)
gitlab-markup (1.7.0)
gitlab-sidekiq-fetcher (0.4.0)
sidekiq (~> 5)
gitlab-styles (2.6.2)
rubocop (~> 0.68.1)
gitlab-styles (2.7.0)
rubocop (~> 0.69.0)
rubocop-gitlab-security (~> 0.1.0)
rubocop-performance (~> 1.1.0)
rubocop-rspec (~> 1.19)
@ -358,7 +376,7 @@ GEM
haml (5.0.4)
temple (>= 0.8.0)
tilt
haml_lint (0.30.0)
haml_lint (0.31.0)
haml (>= 4.0, < 5.1)
rainbow
rake (>= 10, < 13)
@ -375,6 +393,7 @@ GEM
hashie (>= 3.0)
health_check (2.6.0)
rails (>= 4.0)
heapy (0.1.4)
hipchat (1.5.2)
httparty
mimemagic
@ -476,16 +495,17 @@ GEM
memoist (0.16.0)
memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1)
memory_profiler (0.9.13)
method_source (0.9.2)
mime-types (3.2.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
mime-types-data (3.2019.0331)
mimemagic (0.3.2)
mini_magick (4.8.0)
mini_mime (1.0.1)
mini_portile2 (2.4.0)
minitest (5.11.3)
msgpack (1.2.6)
msgpack (1.2.10)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
@ -570,7 +590,7 @@ GEM
activesupport
nokogiri (>= 1.4.4)
omniauth (~> 1.0)
omniauth_openid_connect (0.3.0)
omniauth_openid_connect (0.3.1)
addressable (~> 2.5)
omniauth (~> 1.3)
openid_connect (~> 1.1)
@ -591,7 +611,7 @@ GEM
orm_adapter (0.5.0)
os (1.0.0)
parallel (1.17.0)
parser (2.5.3.0)
parser (2.6.3.0)
ast (~> 2.4.0)
parslet (1.8.2)
peek (1.0.1)
@ -641,7 +661,7 @@ GEM
pry (~> 0.10)
pry-rails (0.3.6)
pry (>= 0.10.4)
public_suffix (3.0.3)
public_suffix (3.1.0)
puma (3.12.0)
puma_worker_killer (0.1.0)
get_process_mem (~> 0.2)
@ -666,6 +686,7 @@ GEM
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
rack-timeout (0.5.1)
rails (5.1.7)
actioncable (= 5.1.7)
actionmailer (= 5.1.7)
@ -732,7 +753,7 @@ GEM
redis-store (>= 1.2, < 2)
redis-store (1.6.0)
redis (>= 2.2, < 5)
regexp_parser (1.4.0)
regexp_parser (1.5.1)
regexp_property_values (0.3.4)
representable (3.0.4)
declarative (< 0.1.0)
@ -766,8 +787,8 @@ GEM
rspec-mocks (3.7.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0)
rspec-parameterized (0.4.1)
binding_ninja (>= 0.2.1)
rspec-parameterized (0.4.2)
binding_ninja (>= 0.2.3)
parser
proc_to_ast
rspec (>= 2.13, < 4)
@ -791,13 +812,13 @@ GEM
pg
rails
sqlite3
rubocop (0.68.1)
rubocop (0.69.0)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.5, != 2.5.1.1)
parser (>= 2.6)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.6)
unicode-display_width (>= 1.4.0, < 1.7)
rubocop-gitlab-security (0.1.1)
rubocop (>= 0.51)
rubocop-performance (1.1.0)
@ -812,7 +833,7 @@ GEM
ruby-progressbar (1.10.0)
ruby-saml (1.7.2)
nokogiri (>= 1.5.10)
ruby_parser (3.11.0)
ruby_parser (3.13.1)
sexp_processor (~> 4.9)
rubyntlm (0.6.2)
rubypants (0.2.0)
@ -852,11 +873,11 @@ GEM
sentry-raven (2.9.0)
faraday (>= 0.7.6, < 1.0)
settingslogic (2.0.9)
sexp_processor (4.11.0)
sexp_processor (4.12.0)
sham_rack (1.3.6)
rack
shoulda-matchers (3.1.2)
activesupport (>= 4.0.0)
shoulda-matchers (4.0.1)
activesupport (>= 4.2.0)
sidekiq (5.2.7)
connection_pool (~> 2.2, >= 2.2.2)
rack (>= 1.5.0)
@ -871,11 +892,11 @@ GEM
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simple_po_parser (1.1.2)
simplecov (0.14.1)
docile (~> 1.1.0)
simplecov (0.16.1)
docile (~> 1.1)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.0)
simplecov-html (0.10.2)
slack-notifier (1.5.1)
spring (2.0.2)
activesupport (>= 4.2)
@ -935,7 +956,7 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.7.5)
unicode-display_width (1.5.0)
unicode-display_width (1.6.0)
unicorn (5.4.1)
kgio (~> 2.6)
raindrops (~> 0.7)
@ -943,13 +964,13 @@ GEM
get_process_mem (~> 0)
unicorn (>= 4, < 6)
uniform_notifier (1.10.0)
unparser (0.4.2)
unparser (0.4.5)
abstract_type (~> 0.0.7)
adamantium (~> 0.2.0)
concord (~> 0.1.5)
diff-lcs (~> 1.3)
equalizer (~> 0.0.9)
parser (>= 2.3.1.2, < 2.6)
parser (~> 2.6.3)
procto (~> 0.0.2)
validate_email (0.1.6)
activemodel (>= 3.0)
@ -996,6 +1017,8 @@ PLATFORMS
DEPENDENCIES
RedCloth (~> 4.3.2)
ace-rails-ap (~> 4.1.0)
acme-client (~> 2.0.2)
activerecord-explain-analyze (~> 0.1)
activerecord_sane_schema_dumper (= 1.0)
acts-as-taggable-on (~> 6.0)
addressable (~> 2.5.2)
@ -1003,6 +1026,7 @@ DEPENDENCIES
apollo_upload_server (~> 2.0.0.beta3)
asana (~> 0.8.1)
asciidoctor (~> 1.5.8)
asciidoctor-include-ext (~> 0.3.1)
asciidoctor-plantuml (= 0.0.8)
attr_encrypted (~> 3.1.0)
awesome_print
@ -1011,6 +1035,7 @@ DEPENDENCIES
batch-loader (~> 1.4.0)
bcrypt_pbkdf (~> 1.0)
benchmark-ips (~> 2.3.0)
benchmark-memory (~> 0.1)
better_errors (~> 2.5.0)
binding_of_caller (~> 0.8.0)
bootsnap (~> 1.4)
@ -1019,7 +1044,7 @@ DEPENDENCIES
browser (~> 2.5)
bullet (~> 5.5.0)
bundler-audit (~> 0.5.0)
capybara (~> 2.18.0)
capybara (~> 3.22.0)
capybara-screenshot (~> 1.0.22)
carrierwave (~> 1.3)
charlock_holmes (~> 0.7.5)
@ -1031,8 +1056,9 @@ DEPENDENCIES
creole (~> 0.5.0)
database_cleaner (~> 1.7.0)
deckar01-task_list (= 2.2.0)
derailed_benchmarks
device_detector
devise (~> 4.4)
devise (~> 4.6)
devise-two-factor (~> 3.0.0)
diffy (~> 3.1.0)
discordrb-webhooks-blackst0ne (~> 3.3)
@ -1059,19 +1085,19 @@ DEPENDENCIES
fog-rackspace (~> 0.1.1)
font-awesome-rails (~> 4.7)
foreman (~> 0.84.0)
fugit (~> 1.1)
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-proto (~> 1.27.2)
gitaly-proto (~> 1.32.0)
github-markup (~> 1.7.0)
gitlab-default_value_for (~> 3.1.1)
gitlab-labkit (~> 0.2.0)
gitlab-labkit (~> 0.3.0)
gitlab-markup (~> 1.7.0)
gitlab-sidekiq-fetcher (~> 0.4.0)
gitlab-styles (~> 2.6)
gitlab-styles (~> 2.7)
gitlab_omniauth-ldap (~> 2.1.1)
gon (~> 6.2)
google-api-client (~> 0.23)
@ -1084,7 +1110,7 @@ DEPENDENCIES
graphiql-rails (~> 1.4.10)
graphql (~> 1.8.0)
grpc (~> 1.19.0)
haml_lint (~> 0.30.0)
haml_lint (~> 0.31.0)
hamlit (~> 2.8.8)
hangouts-chat (~> 0.0.5)
hashie-forbidden_attributes
@ -1108,6 +1134,7 @@ DEPENDENCIES
lograge (~> 0.5)
loofah (~> 2.2)
mail_room (~> 0.9.1)
memory_profiler (~> 0.9)
method_source (~> 0.8)
mimemagic (~> 0.3.2)
mini_magick
@ -1136,7 +1163,7 @@ DEPENDENCIES
omniauth-twitter (~> 1.4)
omniauth-ultraauth (~> 0.0.2)
omniauth_crowd (~> 2.2.0)
omniauth_openid_connect (~> 0.3.0)
omniauth_openid_connect (~> 0.3.1)
org-ruby (~> 0.9.12)
peek (~> 1.0.1)
peek-gc (~> 0.0.2)
@ -1156,6 +1183,7 @@ DEPENDENCIES
rack-cors (~> 1.0.0)
rack-oauth2 (~> 1.9.3)
rack-proxy (~> 0.6.0)
rack-timeout
rails (= 5.1.7)
rails-controller-testing
rails-i18n (~> 5.1)
@ -1179,7 +1207,7 @@ DEPENDENCIES
rspec-set (~> 0.1.3)
rspec_junit_formatter
rspec_profiling (~> 0.0.5)
rubocop (~> 0.68.1)
rubocop (~> 0.69.0)
rubocop-performance (~> 1.1.0)
rubocop-rspec (~> 1.22.1)
ruby-fogbugz (~> 0.2.1)
@ -1193,14 +1221,14 @@ DEPENDENCIES
scss_lint (~> 0.56.0)
seed-fu (~> 2.3.7)
selenium-webdriver (~> 3.141)
sentry-raven (~> 2.7)
sentry-raven (~> 2.9)
settingslogic (~> 2.0.9)
sham_rack (~> 1.3.6)
shoulda-matchers (~> 3.1.2)
shoulda-matchers (~> 4.0.1)
sidekiq (~> 5.2.7)
sidekiq-cron (~> 1.0)
simple_po_parser (~> 1.1.2)
simplecov (~> 0.14.0)
simplecov (~> 0.16.1)
slack-notifier (~> 1.5.1)
spring (~> 2.0.0)
spring-commands-rspec (~> 1.0.4)

View file

@ -86,21 +86,10 @@ 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 7th at 23:59 (Pacific Time Zone) of each month, stable branch and RC1
of the upcoming release (to be shipped on the 22nd) is created and deployed to GitLab.com.
The stable branch is frozen at the most recent "qualifying commit" on master.
A "qualifying commit" is one that is pushed before the feature freeze cutoff time
and that passes all CI jobs (green pipeline).
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.
The feature freeze on the 7th has been discontinued. The [transition period overview](https://gitlab.com/gitlab-org/release/docs/blob/21cbd409dd5f157fe252f254f3e897f01908abe2/general/deploy/auto-deploy-transition.md#transition)
describes the change to this process. During the transition period, the only guarantee that
a change will be included in the release on the 22nd is if the change has been
deployed to GitLab.com prior to this date.
### Feature flags
@ -113,7 +102,7 @@ corresponding exception request to be created.
A level of common sense should be applied when deciding whether to have a feature
behind a feature flag off or on by default.
The following guideliness can be applied to help make this decision:
The following guidelines can be applied to help make this decision:
* If the feature is not fully ready or functioning, the feature flag should be disabled by default.
* If the feature is ready but there are concerns about performance or impact, the feature flag should be enabled by default, but
@ -125,7 +114,7 @@ For more information on rolling out changes using feature flags, read [through t
In order to build the final package and present the feature for self-hosted
customers, the feature flag should be removed. This should happen before the
22nd, ideally _at least_ 2 days before. That means MRs with feature
flags being picked at the 19th would have a quite tight schedule, so picking
flags being picked at the 19th would have quite a tight schedule, so picking
these _earlier_ is preferable.
While rare, release managers may decide to reject picking a change into a stable

View file

@ -54,8 +54,6 @@ Just select your operating system, download the respective package (Debian or RP
There are various other options to install GitLab, please refer to the [installation page on the GitLab website](https://about.gitlab.com/installation/) for more information.
You can access a new installation with the login **`root`** and password **`5iveL!fe`**, after login you are required to set a unique password.
## Contributing
GitLab is an open source project and we are very happy to accept community contributions. Please refer to [Contributing to GitLab page](https://about.gitlab.com/contributing/) for more details.
@ -125,4 +123,3 @@ Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on
## Is it awesome?
[These people](https://twitter.com/gitlab/likes) seem to like it.

View file

@ -1 +1 @@
11.11.8
12.0.8

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -12,7 +12,7 @@ const Api = {
groupProjectsPath: '/api/:version/groups/:id/projects.json',
projectsPath: '/api/:version/projects.json',
projectPath: '/api/:version/projects/:id',
projectLabelsPath: '/:namespace_path/:project_path/labels',
projectLabelsPath: '/:namespace_path/:project_path/-/labels',
projectMergeRequestsPath: '/api/:version/projects/:id/merge_requests',
projectMergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid',
projectMergeRequestChangesPath: '/api/:version/projects/:id/merge_requests/:mrid/changes',

View file

@ -1,4 +1,4 @@
/* eslint-disable class-methods-use-this */
/* eslint-disable class-methods-use-this, @gitlab/i18n/no-non-i18n-strings */
import $ from 'jquery';
import _ from 'underscore';

View file

@ -1,10 +1,12 @@
import { sprintf, __ } from '~/locale';
export default {
computed: {
resolveButtonTitle() {
let title = 'Mark as resolved';
let title = __('Mark comment as resolved');
if (this.resolvedBy) {
title = `Resolved by ${this.resolvedBy.name}`;
title = sprintf(__('Resolved by %{name}'), { name: this.resolvedBy.name });
}
return title;

View file

@ -1,6 +1,5 @@
import $ from 'jquery';
import { __ } from '~/locale';
import flash from '~/flash';
import { s__, sprintf } from '~/locale';
// Renders math using KaTeX in any element with the
// `js-render-math` class
@ -10,21 +9,131 @@ import flash from '~/flash';
// <code class="js-render-math"></div>
//
// Loop over all math elements and render math
function renderWithKaTeX(elements, katex) {
elements.each(function katexElementsLoop() {
const mathNode = $('<span></span>');
const $this = $(this);
const MAX_MATH_CHARS = 1000;
const MAX_RENDER_TIME_MS = 2000;
const display = $this.attr('data-math-style') === 'display';
try {
katex.render($this.text(), mathNode.get(0), { displayMode: display, throwOnError: false });
mathNode.insertAfter($this);
$this.remove();
} catch (err) {
throw err;
// These messages might be used with inline errors in the future. Keep them around. For now, we will
// display a single error message using flash().
// const CHAR_LIMIT_EXCEEDED_MSG = sprintf(
// s__(
// 'math|The following math is too long. For performance reasons, math blocks are limited to %{maxChars} characters. Try splitting up this block, or include an image instead.',
// ),
// { maxChars: MAX_MATH_CHARS },
// );
// const RENDER_TIME_EXCEEDED_MSG = s__(
// "math|The math in this entry is taking too long to render. Any math below this point won't be shown. Consider splitting it among multiple entries.",
// );
const RENDER_FLASH_MSG = sprintf(
s__(
'math|The math in this entry is taking too long to render and may not be displayed as expected. For performance reasons, math blocks are also limited to %{maxChars} characters. Consider splitting up large formulae, splitting math blocks among multiple entries, or using an image instead.',
),
{ maxChars: MAX_MATH_CHARS },
);
// Wait for the browser to reflow the layout. Reflowing SVG takes time.
// This has to wrap the inner function, otherwise IE/Edge throw "invalid calling object".
const waitForReflow = fn => {
window.requestAnimationFrame(fn);
};
/**
* Renders math blocks sequentially while protecting against DoS attacks. Math blocks have a maximum character limit of MAX_MATH_CHARS. If rendering math takes longer than MAX_RENDER_TIME_MS, all subsequent math blocks are skipped and an error message is shown.
*/
class SafeMathRenderer {
/*
How this works:
The performance bottleneck in rendering math is in the browser trying to reflow the generated SVG.
During this time, the JS is blocked and the page becomes unresponsive.
We want to render math blocks one by one until a certain time is exceeded, after which we stop
rendering subsequent math blocks, to protect against DoS. However, browsers do reflowing in an
asynchronous task, so we can't time it synchronously.
SafeMathRenderer essentially does the following:
1. Replaces all math blocks with placeholders so that they're not mistakenly rendered twice.
2. Places each placeholder element in a queue.
3. Renders the element at the head of the queue and waits for reflow.
4. After reflow, gets the elapsed time since step 3 and repeats step 3 until the queue is empty.
*/
queue = [];
totalMS = 0;
constructor(elements, katex) {
this.elements = elements;
this.katex = katex;
this.renderElement = this.renderElement.bind(this);
this.render = this.render.bind(this);
}
renderElement() {
if (!this.queue.length) {
return;
}
const el = this.queue.shift();
const text = el.textContent;
el.removeAttribute('style');
if (this.totalMS >= MAX_RENDER_TIME_MS || text.length > MAX_MATH_CHARS) {
if (!this.flashShown) {
flash(RENDER_FLASH_MSG);
this.flashShown = true;
}
// Show unrendered math code
const codeElement = document.createElement('pre');
codeElement.className = 'code';
codeElement.textContent = el.textContent;
el.parentNode.replaceChild(codeElement, el);
// Render the next math
this.renderElement();
} else {
this.startTime = Date.now();
try {
el.innerHTML = this.katex.renderToString(text, {
displayMode: el.getAttribute('data-math-style') === 'display',
throwOnError: true,
maxSize: 20,
maxExpand: 20,
});
} catch {
// Don't show a flash for now because it would override an existing flash message
el.textContent = s__('math|There was an error rendering this math block');
// el.style.color = '#d00';
el.className = 'katex-error';
}
// Give the browser time to reflow the svg
waitForReflow(() => {
const deltaTime = Date.now() - this.startTime;
this.totalMS += deltaTime;
this.renderElement();
});
}
}
render() {
// Replace math blocks with a placeholder so they aren't rendered twice
this.elements.forEach(el => {
const placeholder = document.createElement('span');
placeholder.style.display = 'none';
placeholder.setAttribute('data-math-style', el.getAttribute('data-math-style'));
placeholder.textContent = el.textContent;
el.parentNode.replaceChild(placeholder, el);
this.queue.push(placeholder);
});
// If we wait for the browser thread to settle down a bit, math rendering becomes 5-10x faster
// and less prone to timeouts.
setTimeout(this.renderElement, 400);
}
}
export default function renderMath($els) {
@ -34,7 +143,8 @@ export default function renderMath($els) {
import(/* webpackChunkName: 'katex' */ 'katex/dist/katex.min.css'),
])
.then(([katex]) => {
renderWithKaTeX($els, katex);
const renderer = new SafeMathRenderer($els.get(), katex);
renderer.render();
})
.catch(() => flash(__('An error occurred while rendering KaTeX')));
.catch(() => {});
}

View file

@ -15,7 +15,7 @@ import { sprintf, __ } from '../../locale';
// </pre>
//
// This is an arbitary number; Can be iterated upon when suitable.
// This is an arbitrary number; Can be iterated upon when suitable.
const MAX_CHAR_LIMIT = 5000;
export default function renderMermaid($els) {

View file

@ -37,7 +37,7 @@ export default class ShortcutsIssuable extends Shortcuts {
}
// Sanity check: Make sure the selected text comes from a discussion : it can either contain a message...
let foundMessage = !!documentFragment.querySelector('.md');
let foundMessage = Boolean(documentFragment.querySelector('.md'));
// ... Or come from a message
if (!foundMessage) {

View file

@ -1,6 +1,5 @@
<script>
/* global ListLabel */
import _ from 'underscore';
import Cookies from 'js-cookie';
import boardsStore from '../stores/boards_store';
@ -29,8 +28,6 @@ export default {
});
});
boardsStore.state.lists = _.sortBy(boardsStore.state.lists, 'position');
// Save the labels
gl.boardService
.generateDefaultLists()

View file

@ -66,7 +66,7 @@ export default {
eventHub.$emit('clearDetailIssue');
} else {
eventHub.$emit('newDetailIssue', this.issue);
boardsStore.detail.list = this.list;
boardsStore.setListDetail(this.list);
}
}
},

View file

@ -142,8 +142,10 @@ export default {
const card = this.$refs.issue[e.oldIndex];
card.showDetail = false;
boardsStore.moving.list = card.list;
boardsStore.moving.issue = boardsStore.moving.list.findIssue(+e.item.dataset.issueId);
const { list } = card;
const issue = list.findIssue(Number(e.item.dataset.issueId));
boardsStore.startMoving(list, issue);
sortableStart();
},

View file

@ -72,8 +72,8 @@ export default {
// Need this because our jQuery very kindly disables buttons on ALL form submissions
$(this.$refs.submitButton).enable();
boardsStore.detail.issue = issue;
boardsStore.detail.list = this.list;
boardsStore.setIssueDetail(issue);
boardsStore.setListDetail(this.list);
})
.catch(() => {
// Need this because our jQuery very kindly disables buttons on ALL form submissions

View file

@ -6,7 +6,6 @@ import Icon from '~/vue_shared/components/icon.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import issueCardInner from 'ee_else_ce/boards/mixins/issue_card_inner';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import eventHub from '../eventhub';
import IssueDueDate from './issue_due_date.vue';
import IssueTimeEstimate from './issue_time_estimate.vue';
import boardsStore from '../stores/boards_store';
@ -136,23 +135,7 @@ export default {
const labelTitle = encodeURIComponent(label.title);
const filter = `label_name[]=${labelTitle}`;
this.applyFilter(filter);
},
applyFilter(filter) {
const filterPath = boardsStore.filter.path.split('&');
const filterIndex = filterPath.indexOf(filter);
if (filterIndex === -1) {
filterPath.push(filter);
} else {
filterPath.splice(filterIndex, 1);
}
boardsStore.filter.path = filterPath.join('&');
boardsStore.updateFiltersUrl();
eventHub.$emit('updateTokens');
boardsStore.toggleFilter(filter);
},
labelStyle(label) {
return {

View file

@ -124,7 +124,7 @@ export default {
data.issues.forEach(issueObj => {
const issue = new ListIssue(issueObj);
const foundSelectedIssue = ModalStore.findSelectedIssue(issue);
issue.selected = !!foundSelectedIssue;
issue.selected = Boolean(foundSelectedIssue);
this.issues.push(issue);
});

View file

@ -2,7 +2,6 @@
import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
import _ from 'underscore';
import CreateLabelDropdown from '../../create_label';
import boardsStore from '../stores/boards_store';
@ -78,8 +77,6 @@ export default function initNewListDropdown() {
color: label.color,
},
});
boardsStore.state.lists = _.sortBy(boardsStore.state.lists, 'position');
}
},
});

View file

@ -48,7 +48,7 @@ export default Vue.extend({
list.removeIssue(issue);
});
boardsStore.detail.issue = {};
boardsStore.clearDetailIssue();
},
/**
* Build the default patch request.

View file

@ -1,11 +1,10 @@
import $ from 'jquery';
import _ from 'underscore';
import Vue from 'vue';
import Flash from '~/flash';
import { __ } from '~/locale';
import '~/vue_shared/models/label';
import '~/vue_shared/models/assignee';
import './models/label';
import './models/assignee';
import FilteredSearchBoards from './filtered_search_boards';
import eventHub from './eventhub';
@ -106,18 +105,23 @@ export default () => {
gl.boardService
.all()
.then(res => res.data)
.then(data => {
data.forEach(board => {
const list = boardsStore.addList(board, this.defaultAvatar);
if (list.type === 'closed') {
list.position = Infinity;
} else if (list.type === 'backlog') {
list.position = -1;
.then(lists => {
lists.forEach(listObj => {
let { position } = listObj;
if (listObj.list_type === 'closed') {
position = Infinity;
} else if (listObj.list_type === 'backlog') {
position = -1;
}
});
this.state.lists = _.sortBy(this.state.lists, 'position');
boardsStore.addList(
{
...listObj,
position,
},
this.defaultAvatar,
);
});
boardsStore.addBlankState();
this.loading = false;
@ -164,10 +168,10 @@ export default () => {
});
}
boardsStore.detail.issue = newIssue;
boardsStore.setIssueDetail(newIssue);
},
clearDetailIssue() {
boardsStore.detail.issue = {};
boardsStore.clearDetailIssue();
},
toggleSubscription(id) {
const { issue } = boardsStore.detail;

View file

@ -4,7 +4,7 @@
/* global ListAssignee */
import Vue from 'vue';
import '~/vue_shared/models/label';
import './label';
import { isEE, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import IssueProject from './project';
import boardsStore from '../stores/boards_store';

View file

@ -0,0 +1,11 @@
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
export default class ListLabel {
constructor(obj) {
Object.assign(this, convertObjectPropsToCamelCase(obj, { dropKeys: ['priority'] }), {
priority: obj.priority !== null ? obj.priority : Infinity,
});
}
}
window.ListLabel = ListLabel;

View file

@ -2,8 +2,8 @@
/* global ListIssue */
import { __ } from '~/locale';
import ListLabel from '~/vue_shared/models/label';
import ListAssignee from '~/vue_shared/models/assignee';
import ListLabel from './label';
import ListAssignee from './assignee';
import { isEE, urlParamsToObject } from '~/lib/utils/common_utils';
import boardsStore from '../stores/boards_store';
import ListMilestone from './milestone';
@ -37,8 +37,8 @@ class List {
this.type = obj.list_type;
const typeInfo = this.getTypeInfo(this.type);
this.preset = !!typeInfo.isPreset;
this.isExpandable = !!typeInfo.isExpandable;
this.preset = Boolean(typeInfo.isPreset);
this.isExpandable = Boolean(typeInfo.isExpandable);
this.isExpanded = true;
this.page = 1;
this.loading = true;

View file

@ -0,0 +1,66 @@
const notImplemented = () => {
/* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
throw new Error('Not implemented!');
};
export default {
setEndpoints: () => {
notImplemented();
},
fetchLists: () => {
notImplemented();
},
generateDefaultLists: () => {
notImplemented();
},
createList: () => {
notImplemented();
},
updateList: () => {
notImplemented();
},
deleteList: () => {
notImplemented();
},
fetchIssuesForList: () => {
notImplemented();
},
moveIssue: () => {
notImplemented();
},
createNewIssue: () => {
notImplemented();
},
fetchBacklog: () => {
notImplemented();
},
bulkUpdateIssues: () => {
notImplemented();
},
fetchIssue: () => {
notImplemented();
},
toggleIssueSubscription: () => {
notImplemented();
},
showPage: () => {
notImplemented();
},
toggleEmptyState: () => {
notImplemented();
},
};

View file

@ -8,6 +8,7 @@ import Cookies from 'js-cookie';
import BoardsStoreEE from 'ee_else_ce/boards/stores/boards_store_ee';
import { getUrlParamsArray, parseBoolean } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
import eventHub from '../eventhub';
const boardsStore = {
disabled: false,
@ -45,7 +46,7 @@ const boardsStore = {
},
addList(listObj, defaultAvatar) {
const list = new List(listObj, defaultAvatar);
this.state.lists.push(list);
this.state.lists = _.sortBy([...this.state.lists, list], 'position');
return list;
},
@ -82,8 +83,6 @@ const boardsStore = {
title: __('Welcome to your Issue Board!'),
position: 0,
});
this.state.lists = _.sortBy(this.state.lists, 'position');
},
removeBlankState() {
this.removeList('blank');
@ -111,6 +110,11 @@ const boardsStore = {
});
listFrom.update();
},
startMoving(list, issue) {
Object.assign(this.moving, { list, issue });
},
moveIssueToList(listFrom, listTo, issue, newIndex) {
const issueTo = listTo.findIssue(issue.id);
const issueLists = issue.getLists();
@ -185,9 +189,39 @@ const boardsStore = {
findListByLabelId(id) {
return this.state.lists.find(list => list.type === 'label' && list.label.id === id);
},
toggleFilter(filter) {
const filterPath = this.filter.path.split('&');
const filterIndex = filterPath.indexOf(filter);
if (filterIndex === -1) {
filterPath.push(filter);
} else {
filterPath.splice(filterIndex, 1);
}
this.filter.path = filterPath.join('&');
this.updateFiltersUrl();
eventHub.$emit('updateTokens');
},
setListDetail(newList) {
this.detail.list = newList;
},
updateFiltersUrl() {
window.history.pushState(null, null, `?${this.filter.path}`);
},
clearDetailIssue() {
this.setIssueDetail({});
},
setIssueDetail(issueDetail) {
this.detail.issue = issueDetail;
},
};
BoardsStoreEE.initEESpecific(boardsStore);

View file

@ -0,0 +1,14 @@
import Vue from 'vue';
import Vuex from 'vuex';
import state from 'ee_else_ce/boards/stores/state';
import actions from 'ee_else_ce/boards/stores/actions';
import mutations from 'ee_else_ce/boards/stores/mutations';
Vue.use(Vuex);
export default () =>
new Vuex.Store({
state,
actions,
mutations,
});

View file

@ -0,0 +1,21 @@
export const SET_ENDPOINTS = 'SET_ENDPOINTS';
export const REQUEST_ADD_LIST = 'REQUEST_ADD_LIST';
export const RECEIVE_ADD_LIST_SUCCESS = 'RECEIVE_ADD_LIST_SUCCESS';
export const RECEIVE_ADD_LIST_ERROR = 'RECEIVE_ADD_LIST_ERROR';
export const REQUEST_UPDATE_LIST = 'REQUEST_UPDATE_LIST';
export const RECEIVE_UPDATE_LIST_SUCCESS = 'RECEIVE_UPDATE_LIST_SUCCESS';
export const RECEIVE_UPDATE_LIST_ERROR = 'RECEIVE_UPDATE_LIST_ERROR';
export const REQUEST_REMOVE_LIST = 'REQUEST_REMOVE_LIST';
export const RECEIVE_REMOVE_LIST_SUCCESS = 'RECEIVE_REMOVE_LIST_SUCCESS';
export const RECEIVE_REMOVE_LIST_ERROR = 'RECEIVE_REMOVE_LIST_ERROR';
export const REQUEST_ADD_ISSUE = 'REQUEST_ADD_ISSUE';
export const RECEIVE_ADD_ISSUE_SUCCESS = 'RECEIVE_ADD_ISSUE_SUCCESS';
export const RECEIVE_ADD_ISSUE_ERROR = 'RECEIVE_ADD_ISSUE_ERROR';
export const REQUEST_MOVE_ISSUE = 'REQUEST_MOVE_ISSUE';
export const RECEIVE_MOVE_ISSUE_SUCCESS = 'RECEIVE_MOVE_ISSUE_SUCCESS';
export const RECEIVE_MOVE_ISSUE_ERROR = 'RECEIVE_MOVE_ISSUE_ERROR';
export const REQUEST_UPDATE_ISSUE = 'REQUEST_UPDATE_ISSUE';
export const RECEIVE_UPDATE_ISSUE_SUCCESS = 'RECEIVE_UPDATE_ISSUE_SUCCESS';
export const RECEIVE_UPDATE_ISSUE_ERROR = 'RECEIVE_UPDATE_ISSUE_ERROR';
export const SET_CURRENT_PAGE = 'SET_CURRENT_PAGE';
export const TOGGLE_EMPTY_STATE = 'TOGGLE_EMPTY_STATE';

View file

@ -0,0 +1,92 @@
import * as mutationTypes from './mutation_types';
const notImplemented = () => {
/* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
throw new Error('Not implemented!');
};
export default {
[mutationTypes.SET_ENDPOINTS]: () => {
notImplemented();
},
[mutationTypes.REQUEST_ADD_LIST]: () => {
notImplemented();
},
[mutationTypes.RECEIVE_ADD_LIST_SUCCESS]: () => {
notImplemented();
},
[mutationTypes.RECEIVE_ADD_LIST_ERROR]: () => {
notImplemented();
},
[mutationTypes.REQUEST_UPDATE_LIST]: () => {
notImplemented();
},
[mutationTypes.RECEIVE_UPDATE_LIST_SUCCESS]: () => {
notImplemented();
},
[mutationTypes.RECEIVE_UPDATE_LIST_ERROR]: () => {
notImplemented();
},
[mutationTypes.REQUEST_REMOVE_LIST]: () => {
notImplemented();
},
[mutationTypes.RECEIVE_REMOVE_LIST_SUCCESS]: () => {
notImplemented();
},
[mutationTypes.RECEIVE_REMOVE_LIST_ERROR]: () => {
notImplemented();
},
[mutationTypes.REQUEST_ADD_ISSUE]: () => {
notImplemented();
},
[mutationTypes.RECEIVE_ADD_ISSUE_SUCCESS]: () => {
notImplemented();
},
[mutationTypes.RECEIVE_ADD_ISSUE_ERROR]: () => {
notImplemented();
},
[mutationTypes.REQUEST_MOVE_ISSUE]: () => {
notImplemented();
},
[mutationTypes.RECEIVE_MOVE_ISSUE_SUCCESS]: () => {
notImplemented();
},
[mutationTypes.RECEIVE_MOVE_ISSUE_ERROR]: () => {
notImplemented();
},
[mutationTypes.REQUEST_UPDATE_ISSUE]: () => {
notImplemented();
},
[mutationTypes.RECEIVE_UPDATE_ISSUE_SUCCESS]: () => {
notImplemented();
},
[mutationTypes.RECEIVE_UPDATE_ISSUE_ERROR]: () => {
notImplemented();
},
[mutationTypes.SET_CURRENT_PAGE]: () => {
notImplemented();
},
[mutationTypes.TOGGLE_EMPTY_STATE]: () => {
notImplemented();
},
};

View file

@ -0,0 +1,3 @@
export default () => ({
// ...
});

View file

@ -23,7 +23,7 @@ class DeleteModal {
const branchData = e.currentTarget.dataset;
this.branchName = branchData.branchName || '';
this.deletePath = branchData.deletePath || '';
this.isMerged = !!branchData.isMerged;
this.isMerged = Boolean(branchData.isMerged);
this.updateModal();
}

View file

@ -27,15 +27,24 @@ function generateErrorBoxContent(errors) {
// Used for the variable list on CI/CD projects/groups settings page
export default class AjaxVariableList {
constructor({ container, saveButton, errorBox, formField = 'variables', saveEndpoint }) {
constructor({
container,
saveButton,
errorBox,
formField = 'variables',
saveEndpoint,
maskableRegex,
}) {
this.container = container;
this.saveButton = saveButton;
this.errorBox = errorBox;
this.saveEndpoint = saveEndpoint;
this.maskableRegex = maskableRegex;
this.variableList = new VariableList({
container: this.container,
formField,
maskableRegex,
});
this.bindEvents();

View file

@ -16,9 +16,10 @@ function createEnvironmentItem(value) {
}
export default class VariableList {
constructor({ container, formField }) {
constructor({ container, formField, maskableRegex }) {
this.$container = $(container);
this.formField = formField;
this.maskableRegex = new RegExp(maskableRegex);
this.environmentDropdownMap = new WeakMap();
this.inputMap = {
@ -196,9 +197,8 @@ export default class VariableList {
validateMaskability($row) {
const invalidInputClass = 'gl-field-error-outline';
const maskableRegex = /^\w{8,}$/; // Eight or more alphanumeric characters plus underscores
const variableValue = $row.find(this.inputMap.secret_value.selector).val();
const isValueMaskable = maskableRegex.test(variableValue) || variableValue === '';
const isValueMaskable = this.maskableRegex.test(variableValue) || variableValue === '';
const isMaskedChecked = $row.find(this.inputMap.masked.selector).val() === 'true';
// Show a validation error if the user wants to mask an unmaskable variable value

View file

@ -1,5 +1,6 @@
import Visibility from 'visibilityjs';
import Vue from 'vue';
import AccessorUtilities from '~/lib/utils/accessor';
import { GlToast } from '@gitlab/ui';
import PersistentUserCallout from '../persistent_user_callout';
import { s__, sprintf } from '../locale';
@ -43,8 +44,10 @@ export default class Clusters {
helpPath,
ingressHelpPath,
ingressDnsHelpPath,
clusterId,
} = document.querySelector('.js-edit-cluster-form').dataset;
this.clusterId = clusterId;
this.store = new ClustersStore();
this.store.setHelpPaths(helpPath, ingressHelpPath, ingressDnsHelpPath);
this.store.setManagePrometheusPath(managePrometheusPath);
@ -69,6 +72,10 @@ export default class Clusters {
this.errorContainer = document.querySelector('.js-cluster-error');
this.successContainer = document.querySelector('.js-cluster-success');
this.creatingContainer = document.querySelector('.js-cluster-creating');
this.unreachableContainer = document.querySelector('.js-cluster-api-unreachable');
this.authenticationFailureContainer = document.querySelector(
'.js-cluster-authentication-failure',
);
this.errorReasonContainer = this.errorContainer.querySelector('.js-error-reason');
this.successApplicationContainer = document.querySelector('.js-cluster-application-notice');
this.showTokenButton = document.querySelector('.js-show-cluster-token');
@ -125,21 +132,29 @@ export default class Clusters {
PersistentUserCallout.factory(callout);
}
addBannerCloseHandler(el, status) {
el.querySelector('.js-close-banner').addEventListener('click', () => {
el.classList.add('hidden');
this.setBannerDismissedState(status, true);
});
}
addListeners() {
if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken);
eventHub.$on('installApplication', this.installApplication);
eventHub.$on('upgradeApplication', data => this.upgradeApplication(data));
eventHub.$on('dismissUpgradeSuccess', appId => this.dismissUpgradeSuccess(appId));
eventHub.$on('updateApplication', data => this.updateApplication(data));
eventHub.$on('saveKnativeDomain', data => this.saveKnativeDomain(data));
eventHub.$on('setKnativeHostname', data => this.setKnativeHostname(data));
eventHub.$on('uninstallApplication', data => this.uninstallApplication(data));
// Add event listener to all the banner close buttons
this.addBannerCloseHandler(this.unreachableContainer, 'unreachable');
this.addBannerCloseHandler(this.authenticationFailureContainer, 'authentication_failure');
}
removeListeners() {
if (this.showTokenButton) this.showTokenButton.removeEventListener('click', this.showToken);
eventHub.$off('installApplication', this.installApplication);
eventHub.$off('upgradeApplication', this.upgradeApplication);
eventHub.$off('dismissUpgradeSuccess', this.dismissUpgradeSuccess);
eventHub.$off('updateApplication', this.updateApplication);
eventHub.$off('saveKnativeDomain');
eventHub.$off('setKnativeHostname');
eventHub.$off('uninstallApplication');
@ -205,6 +220,8 @@ export default class Clusters {
this.errorContainer.classList.add('hidden');
this.successContainer.classList.add('hidden');
this.creatingContainer.classList.add('hidden');
this.unreachableContainer.classList.add('hidden');
this.authenticationFailureContainer.classList.add('hidden');
}
checkForNewInstalls(prevApplicationMap, newApplicationMap) {
@ -228,9 +245,32 @@ export default class Clusters {
}
}
setBannerDismissedState(status, isDismissed) {
if (AccessorUtilities.isLocalStorageAccessSafe()) {
window.localStorage.setItem(
`cluster_${this.clusterId}_banner_dismissed`,
`${status}_${isDismissed}`,
);
}
}
isBannerDismissed(status) {
let bannerState;
if (AccessorUtilities.isLocalStorageAccessSafe()) {
bannerState = window.localStorage.getItem(`cluster_${this.clusterId}_banner_dismissed`);
}
return bannerState === `${status}_true`;
}
updateContainer(prevStatus, status, error) {
this.hideAll();
if (this.isBannerDismissed(status)) {
return;
}
this.setBannerDismissedState(status, false);
// We poll all the time but only want the `created` banner to show when newly created
if (this.store.state.status !== 'created' || prevStatus !== this.store.state.status) {
switch (status) {
@ -241,6 +281,12 @@ export default class Clusters {
this.errorContainer.classList.remove('hidden');
this.errorReasonContainer.textContent = error;
break;
case 'unreachable':
this.unreachableContainer.classList.remove('hidden');
break;
case 'authentication_failure':
this.authenticationFailureContainer.classList.remove('hidden');
break;
case 'scheduled':
case 'creating':
this.creatingContainer.classList.remove('hidden');
@ -283,19 +329,13 @@ export default class Clusters {
});
}
upgradeApplication(data) {
const appId = data.id;
updateApplication({ id: appId, params }) {
this.store.updateApplication(appId);
this.service.installApplication(appId, data.params).catch(() => {
this.service.installApplication(appId, params).catch(() => {
this.store.notifyUpdateFailure(appId);
});
}
dismissUpgradeSuccess(appId) {
this.store.acknowledgeSuccessfulUpdate(appId);
}
toggleIngressDomainHelpText({ externalIp }, { externalIp: newExternalIp }) {
if (externalIp !== newExternalIp) {
this.ingressDomainHelpText.classList.toggle('hide', !newExternalIp);
@ -305,8 +345,10 @@ export default class Clusters {
saveKnativeDomain(data) {
const appId = data.id;
this.store.updateAppProperty(appId, 'status', APPLICATION_STATUS.UPDATING);
this.service.updateApplication(appId, data.params);
this.store.updateApplication(appId);
this.service.updateApplication(appId, data.params).catch(() => {
this.store.notifyUpdateFailure(appId);
});
}
setKnativeHostname(data) {

View file

@ -2,7 +2,7 @@
/* eslint-disable vue/require-default-prop */
import { GlLink, GlModalDirective } from '@gitlab/ui';
import TimeagoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
import { s__, sprintf } from '../../locale';
import { s__, __, sprintf } from '~/locale';
import eventHub from '../event_hub';
import identicon from '../../vue_shared/components/identicon.vue';
import loadingButton from '../../vue_shared/components/loading_button.vue';
@ -85,10 +85,14 @@ export default {
type: String,
required: false,
},
upgradeAvailable: {
updateAvailable: {
type: Boolean,
required: false,
},
updateable: {
type: Boolean,
default: true,
},
updateSuccessful: {
type: Boolean,
required: false,
@ -109,11 +113,6 @@ export default {
required: false,
default: false,
},
updateAcknowledged: {
type: Boolean,
required: false,
default: true,
},
installApplicationRequestParams: {
type: Object,
required: false,
@ -138,7 +137,7 @@ export default {
);
},
hasLogo() {
return !!this.logoUrl;
return Boolean(this.logoUrl);
},
identiconId() {
// generate a deterministic integer id for the identicon background
@ -170,11 +169,11 @@ export default {
installButtonLabel() {
let label;
if (this.canInstall) {
label = s__('ClusterIntegration|Install');
label = __('Install');
} else if (this.isInstalling) {
label = s__('ClusterIntegration|Installing');
label = __('Installing');
} else if (this.installed) {
label = s__('ClusterIntegration|Installed');
label = __('Installed');
}
return label;
@ -183,7 +182,7 @@ export default {
return this.manageLink && this.status === APPLICATION_STATUS.INSTALLED;
},
manageButtonLabel() {
return s__('ClusterIntegration|Manage');
return __('Manage');
},
hasError() {
return this.installFailed || this.uninstallFailed;
@ -203,42 +202,42 @@ export default {
},
versionLabel() {
if (this.updateFailed) {
return s__('ClusterIntegration|Upgrade failed');
} else if (this.isUpgrading) {
return s__('ClusterIntegration|Upgrading');
return __('Update failed');
} else if (this.isUpdating) {
return __('Updating');
}
return s__('ClusterIntegration|Upgraded');
return __('Updated');
},
upgradeFailureDescription() {
updateFailureDescription() {
return s__('ClusterIntegration|Update failed. Please check the logs and try again.');
},
upgradeSuccessDescription() {
return sprintf(s__('ClusterIntegration|%{title} upgraded successfully.'), {
updateSuccessDescription() {
return sprintf(s__('ClusterIntegration|%{title} updated successfully.'), {
title: this.title,
});
},
upgradeButtonLabel() {
updateButtonLabel() {
let label;
if (this.upgradeAvailable && !this.updateFailed && !this.isUpgrading) {
label = s__('ClusterIntegration|Upgrade');
} else if (this.isUpgrading) {
label = s__('ClusterIntegration|Updating');
if (this.updateAvailable && !this.updateFailed && !this.isUpdating) {
label = __('Update');
} else if (this.isUpdating) {
label = __('Updating');
} else if (this.updateFailed) {
label = s__('ClusterIntegration|Retry update');
label = __('Retry update');
}
return label;
},
isUpgrading() {
isUpdating() {
// Since upgrading is handled asynchronously on the backend we need this check to prevent any delay on the frontend
return this.status === APPLICATION_STATUS.UPDATING;
},
shouldShowUpgradeDetails() {
shouldShowUpdateDetails() {
// This method only returns true when;
// Upgrade was successful OR Upgrade failed
// AND new upgrade is unavailable AND version information is present.
return (this.updateSuccessful || this.updateFailed) && !this.upgradeAvailable && this.version;
// Update was successful OR Update failed
// AND new update is unavailable AND version information is present.
return (this.updateSuccessful || this.updateFailed) && !this.updateAvailable && this.version;
},
uninstallSuccessDescription() {
return sprintf(s__('ClusterIntegration|%{title} uninstalled successfully.'), {
@ -249,7 +248,7 @@ export default {
watch: {
updateSuccessful(updateSuccessful) {
if (updateSuccessful) {
this.$toast.show(this.upgradeSuccessDescription);
this.$toast.show(this.updateSuccessDescription);
}
},
uninstallSuccessful(uninstallSuccessful) {
@ -265,8 +264,8 @@ export default {
params: this.installApplicationRequestParams,
});
},
upgradeClicked() {
eventHub.$emit('upgradeApplication', {
updateClicked() {
eventHub.$emit('updateApplication', {
id: this.id,
params: this.installApplicationRequestParams,
});
@ -326,9 +325,10 @@ export default {
</ul>
</div>
<div v-if="updateable">
<div
v-if="shouldShowUpgradeDetails"
class="form-text text-muted label p-0 js-cluster-application-upgrade-details"
v-if="shouldShowUpdateDetails"
class="form-text text-muted label p-0 js-cluster-application-update-details"
>
{{ versionLabel }}
<span v-if="updateSuccessful">to</span>
@ -337,26 +337,27 @@ export default {
v-if="updateSuccessful"
:href="chartRepo"
target="_blank"
class="js-cluster-application-upgrade-version"
class="js-cluster-application-update-version"
>chart v{{ version }}</gl-link
>
</div>
<div
v-if="updateFailed && !isUpgrading"
class="bs-callout bs-callout-danger cluster-application-banner mt-2 mb-0 js-cluster-application-upgrade-failure-message"
v-if="updateFailed && !isUpdating"
class="bs-callout bs-callout-danger cluster-application-banner mt-2 mb-0 js-cluster-application-update-details"
>
{{ upgradeFailureDescription }}
{{ updateFailureDescription }}
</div>
<loading-button
v-if="upgradeAvailable || updateFailed || isUpgrading"
class="btn btn-primary js-cluster-application-upgrade-button mt-2"
:loading="isUpgrading"
:disabled="isUpgrading"
:label="upgradeButtonLabel"
@click="upgradeClicked"
v-if="updateAvailable || updateFailed || isUpdating"
class="btn btn-primary js-cluster-application-update-button mt-2"
:loading="isUpdating"
:disabled="isUpdating"
:label="updateButtonLabel"
@click="updateClicked"
/>
</div>
</div>
<div
:class="{ 'section-25': showManageButton, 'section-15': !showManageButton }"
class="table-section table-button-footer section-align-top"

View file

@ -15,6 +15,7 @@ import prometheusLogo from 'images/cluster_app_logos/prometheus.png';
import { s__, sprintf } from '../../locale';
import applicationRow from './application_row.vue';
import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
import KnativeDomainEditor from './knative_domain_editor.vue';
import { CLUSTER_TYPE, APPLICATION_STATUS, INGRESS } from '../constants';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import eventHub from '~/clusters/event_hub';
@ -25,6 +26,7 @@ export default {
clipboardButton,
LoadingButton,
GlLoadingIcon,
KnativeDomainEditor,
},
props: {
type: {
@ -154,64 +156,21 @@ export default {
knative() {
return this.applications.knative;
},
knativeInstalled() {
return (
this.knative.status === APPLICATION_STATUS.INSTALLED ||
this.knativeUpgrading ||
this.knativeUpgradeFailed ||
this.knative.status === APPLICATION_STATUS.UPDATED
);
},
knativeUpgrading() {
return (
this.knative.status === APPLICATION_STATUS.UPDATING ||
this.knative.status === APPLICATION_STATUS.SCHEDULED
);
},
knativeUpgradeFailed() {
return this.knative.status === APPLICATION_STATUS.UPDATE_ERRORED;
},
knativeExternalEndpoint() {
return this.knative.externalIp || this.knative.externalHostname;
},
knativeDescription() {
return sprintf(
_.escape(
s__(
`ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}.`,
),
),
{
pricingLink: `<strong><a href="https://cloud.google.com/compute/pricing#lb"
target="_blank" rel="noopener noreferrer">
${_.escape(s__('ClusterIntegration|pricing'))}</a></strong>`,
},
false,
);
},
canUpdateKnativeEndpoint() {
return this.knativeExternalEndpoint && !this.knativeUpgradeFailed && !this.knativeUpgrading;
},
knativeHostname: {
get() {
return this.knative.hostname;
},
set(hostname) {
eventHub.$emit('setKnativeHostname', {
id: 'knative',
hostname,
});
},
},
},
created() {
this.helmInstallIllustration = helmInstallIllustration;
},
methods: {
saveKnativeDomain() {
saveKnativeDomain(hostname) {
eventHub.$emit('saveKnativeDomain', {
id: 'knative',
params: { hostname: this.knative.hostname },
params: { hostname },
});
},
setKnativeHostname(hostname) {
eventHub.$emit('setKnativeHostname', {
id: 'knative',
hostname,
});
},
},
@ -318,9 +277,9 @@ export default {
generated endpoint in order to access
your application after it has been deployed.`)
}}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">{{
__('More information')
}}</a>
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
</a>
</p>
</div>
@ -330,9 +289,9 @@ export default {
the process of being assigned. Please check your Kubernetes
cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
}}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">{{
__('More information')
}}</a>
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
</a>
</p>
</template>
<template v-if="!ingressInstalled">
@ -361,9 +320,9 @@ export default {
<div slot="description">
<p v-html="certManagerDescription"></p>
<div class="form-group">
<label for="cert-manager-issuer-email">{{
s__('ClusterIntegration|Issuer Email')
}}</label>
<label for="cert-manager-issuer-email">
{{ s__('ClusterIntegration|Issuer Email') }}
</label>
<div class="input-group">
<input
v-model="applications.cert_manager.email"
@ -417,7 +376,7 @@ export default {
:request-reason="applications.runner.requestReason"
:version="applications.runner.version"
:chart-repo="applications.runner.chartRepo"
:upgrade-available="applications.runner.upgradeAvailable"
:update-available="applications.runner.updateAvailable"
:installed="applications.runner.installed"
:install-failed="applications.runner.installFailed"
:update-successful="applications.runner.updateSuccessful"
@ -491,9 +450,9 @@ 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.`)
}}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">{{
__('More information')
}}</a>
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
</a>
</p>
</div>
</template>
@ -514,6 +473,7 @@ export default {
:uninstallable="applications.knative.uninstallable"
:uninstall-successful="applications.knative.uninstallSuccessful"
:uninstall-failed="applications.knative.uninstallFailed"
:updateable="false"
:disabled="!helmInstalled"
v-bind="applications.knative"
title-link="https://github.com/knative/docs"
@ -525,9 +485,9 @@ export default {
s__(`ClusterIntegration|You must have an RBAC-enabled cluster
to install Knative.`)
}}
<a :href="helpPath" target="_blank" rel="noopener noreferrer">{{
__('More information')
}}</a>
<a :href="helpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
</a>
</p>
<br />
</span>
@ -540,84 +500,14 @@ export default {
}}
</p>
<div class="row">
<template v-if="knativeInstalled || (helmInstalled && rbac)">
<div
:class="{ 'col-md-6': knativeInstalled, 'col-12': helmInstalled && rbac }"
class="form-group col-sm-12 mb-0"
>
<label for="knative-domainname">
<strong>{{ s__('ClusterIntegration|Knative Domain Name:') }}</strong>
</label>
<input
id="knative-domainname"
v-model="knativeHostname"
type="text"
class="form-control js-knative-domainname"
<knative-domain-editor
v-if="knative.installed || (helmInstalled && rbac)"
:knative="knative"
:ingress-dns-help-path="ingressDnsHelpPath"
@save="saveKnativeDomain"
@set="setKnativeHostname"
/>
</div>
</template>
<template v-if="knativeInstalled">
<div class="form-group col-sm-12 col-md-6 pl-md-0 mb-0 mt-3 mt-md-0">
<label for="knative-endpoint">
<strong>{{ s__('ClusterIntegration|Knative Endpoint:') }}</strong>
</label>
<div v-if="knativeExternalEndpoint" class="input-group">
<input
id="knative-endpoint"
:value="knativeExternalEndpoint"
type="text"
class="form-control js-knative-endpoint"
readonly
/>
<span class="input-group-append">
<clipboard-button
:text="knativeExternalEndpoint"
:title="s__('ClusterIntegration|Copy Knative Endpoint to clipboard')"
class="input-group-text js-knative-endpoint-clipboard-btn"
/>
</span>
</div>
<div v-else class="input-group">
<input type="text" class="form-control js-endpoint" readonly />
<gl-loading-icon
class="position-absolute align-self-center ml-2 js-knative-ip-loading-icon"
/>
</div>
</div>
<p class="form-text text-muted col-12">
{{
s__(
`ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint.`,
)
}}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">{{
__('More information')
}}</a>
</p>
<p
v-if="!knativeExternalEndpoint"
class="settings-message js-no-knative-endpoint-message mt-2 mr-3 mb-0 ml-3"
>
{{
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.`)
}}
</p>
<button
v-if="canUpdateKnativeEndpoint"
class="btn btn-success js-knative-save-domain-button mt-3 ml-3"
@click="saveKnativeDomain"
>
{{ s__('ClusterIntegration|Save changes') }}
</button>
</template>
</div>
</div>
</application-row>
</div>
</section>

View file

@ -0,0 +1,150 @@
<script>
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
import { GlLoadingIcon } from '@gitlab/ui';
import { s__ } from '~/locale';
import { APPLICATION_STATUS } from '~/clusters/constants';
const { UPDATING, UNINSTALLING } = APPLICATION_STATUS;
export default {
components: {
LoadingButton,
ClipboardButton,
GlLoadingIcon,
},
props: {
knative: {
type: Object,
required: true,
},
ingressDnsHelpPath: {
type: String,
default: '',
},
},
computed: {
saveButtonDisabled() {
return [UNINSTALLING, UPDATING].includes(this.knative.status);
},
saving() {
return [UPDATING].includes(this.knative.status);
},
saveButtonLabel() {
return this.saving ? this.__('Saving') : this.__('Save changes');
},
knativeInstalled() {
return this.knative.installed;
},
knativeExternalEndpoint() {
return this.knative.externalIp || this.knative.externalHostname;
},
knativeUpdateSuccessful() {
return this.knative.updateSuccessful;
},
knativeHostname: {
get() {
return this.knative.hostname;
},
set(hostname) {
this.$emit('set', hostname);
},
},
},
watch: {
knativeUpdateSuccessful(updateSuccessful) {
if (updateSuccessful) {
this.$toast.show(s__('ClusterIntegration|Knative domain name was updated successfully.'));
}
},
},
};
</script>
<template>
<div class="row">
<div
v-if="knative.updateFailed"
class="bs-callout bs-callout-danger cluster-application-banner col-12 mt-2 mb-2 js-cluster-knative-domain-name-failure-message"
>
{{ s__('ClusterIntegration|Something went wrong while updating Knative domain name.') }}
</div>
<template>
<div
:class="{ 'col-md-6': knativeInstalled, 'col-12': !knativeInstalled }"
class="form-group col-sm-12 mb-0"
>
<label for="knative-domainname">
<strong>{{ s__('ClusterIntegration|Knative Domain Name:') }}</strong>
</label>
<input
id="knative-domainname"
v-model="knativeHostname"
type="text"
class="form-control js-knative-domainname"
/>
</div>
</template>
<template v-if="knativeInstalled">
<div class="form-group col-sm-12 col-md-6 pl-md-0 mb-0 mt-3 mt-md-0">
<label for="knative-endpoint">
<strong>{{ s__('ClusterIntegration|Knative Endpoint:') }}</strong>
</label>
<div v-if="knativeExternalEndpoint" class="input-group">
<input
id="knative-endpoint"
:value="knativeExternalEndpoint"
type="text"
class="form-control js-knative-endpoint"
readonly
/>
<span class="input-group-append">
<clipboard-button
:text="knativeExternalEndpoint"
:title="s__('ClusterIntegration|Copy Knative Endpoint to clipboard')"
class="input-group-text js-knative-endpoint-clipboard-btn"
/>
</span>
</div>
<div v-else class="input-group">
<input type="text" class="form-control js-endpoint" readonly />
<gl-loading-icon
class="position-absolute align-self-center ml-2 js-knative-ip-loading-icon"
/>
</div>
</div>
<p class="form-text text-muted col-12">
{{
s__(
`ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint.`,
)
}}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
</a>
</p>
<p
v-if="!knativeExternalEndpoint"
class="settings-message js-no-knative-endpoint-message mt-2 mr-3 mb-0 ml-3"
>
{{
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.`)
}}
</p>
<loading-button
class="btn-success js-knative-save-domain-button mt-3 ml-3"
:loading="saving"
:disabled="saveButtonDisabled"
:label="saveButtonLabel"
@click="$emit('save', knativeHostname)"
/>
</template>
</div>
</template>

View file

@ -123,7 +123,6 @@ const applicationStateMachine = {
target: INSTALLED,
effects: {
updateSuccessful: true,
updateAcknowledged: false,
},
},
[UPDATE_ERRORED]: {

View file

@ -56,8 +56,7 @@ export default class ClusterStore {
title: s__('ClusterIntegration|GitLab Runner'),
version: null,
chartRepo: 'https://gitlab.com/charts/gitlab-runner',
upgradeAvailable: null,
updateAcknowledged: true,
updateAvailable: null,
updateSuccessful: false,
updateFailed: false,
},
@ -77,6 +76,8 @@ export default class ClusterStore {
isEditingHostName: false,
externalIp: null,
externalHostname: null,
updateSuccessful: false,
updateFailed: false,
},
},
};
@ -134,10 +135,6 @@ export default class ClusterStore {
this.state.applications[appId] = transitionApplicationState(currentAppState, event);
}
acknowledgeSuccessfulUpdate(appId) {
this.state.applications[appId].updateAcknowledged = true;
}
updateAppProperty(appId, prop, value) {
this.state.applications[appId][prop] = value;
}
@ -152,7 +149,7 @@ export default class ClusterStore {
status,
status_reason: statusReason,
version,
update_available: upgradeAvailable,
update_available: updateAvailable,
can_uninstall: uninstallable,
} = serverAppEntry;
const currentApplicationState = this.state.applications[appId] || {};
@ -189,7 +186,7 @@ export default class ClusterStore {
serverAppEntry.external_hostname || this.state.applications.knative.externalHostname;
} else if (appId === RUNNER) {
this.state.applications.runner.version = version;
this.state.applications.runner.upgradeAvailable = upgradeAvailable;
this.state.applications.runner.updateAvailable = updateAvailable;
}
});
}

View file

@ -2,7 +2,7 @@
import PipelinesService from '../../pipelines/services/pipelines_service';
import PipelineStore from '../../pipelines/stores/pipelines_store';
import pipelinesMixin from '../../pipelines/mixins/pipelines';
import TablePagination from '../../vue_shared/components/table_pagination.vue';
import TablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
import { getParameterByName } from '../../lib/utils/common_utils';
import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';

View file

@ -1,19 +1,21 @@
// ECMAScript polyfills
import 'core-js/fn/array/fill';
import 'core-js/fn/array/find';
import 'core-js/fn/array/find-index';
import 'core-js/fn/array/from';
import 'core-js/fn/array/includes';
import 'core-js/fn/object/assign';
import 'core-js/fn/object/values';
import 'core-js/fn/promise';
import 'core-js/fn/promise/finally';
import 'core-js/fn/string/code-point-at';
import 'core-js/fn/string/from-code-point';
import 'core-js/fn/string/includes';
import 'core-js/fn/symbol';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es/array/fill';
import 'core-js/es/array/find';
import 'core-js/es/array/find-index';
import 'core-js/es/array/from';
import 'core-js/es/array/includes';
import 'core-js/es/object/assign';
import 'core-js/es/object/values';
import 'core-js/es/object/entries';
import 'core-js/es/promise';
import 'core-js/es/promise/finally';
import 'core-js/es/string/code-point-at';
import 'core-js/es/string/from-code-point';
import 'core-js/es/string/includes';
import 'core-js/es/symbol';
import 'core-js/es/map';
import 'core-js/es/weak-map';
import 'core-js/modules/web.url';
// Browser polyfills
import 'formdata-polyfill';

View file

@ -40,7 +40,7 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = (
},
selectable: true,
filterable: true,
filterRemote: !!$dropdown.data('refsUrl'),
filterRemote: Boolean($dropdown.data('refsUrl')),
fieldName: $dropdown.data('fieldName'),
filterInput: 'input[type="search"]',
renderRow: function(ref) {

View file

@ -8,6 +8,8 @@ import { parseBoolean } from '~/lib/utils/common_utils';
// https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24555#note_134136110
const NAV_SIDEBAR_BREAKPOINT = 1200;
export const SIDEBAR_COLLAPSED_CLASS = 'js-sidebar-collapsed';
export default class ContextualSidebar {
constructor() {
this.initDomElements();
@ -62,6 +64,7 @@ export default class ContextualSidebar {
const breakpoint = bp.getBreakpointSize();
const dbp = ContextualSidebar.isDesktopBreakpoint();
this.$sidebar.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show);
this.$sidebar.toggleClass('sidebar-expanded-mobile', !dbp ? show : false);
this.$overlay.toggleClass(
'mobile-nav-open',
@ -75,7 +78,7 @@ export default class ContextualSidebar {
const dbp = ContextualSidebar.isDesktopBreakpoint();
if (this.$sidebar.length) {
this.$sidebar.toggleClass('sidebar-collapsed-desktop', collapsed);
this.$sidebar.toggleClass(`sidebar-collapsed-desktop ${SIDEBAR_COLLAPSED_CLASS}`, collapsed);
this.$sidebar.toggleClass('sidebar-expanded-mobile', !dbp ? !collapsed : false);
this.$page.toggleClass(
'page-with-icon-sidebar',

View file

@ -12,7 +12,7 @@ export default class CreateItemDropdown {
this.fieldName = options.fieldName;
this.onSelect = options.onSelect || (() => {});
this.getDataOption = options.getData;
this.getDataRemote = !!options.filterRemote;
this.getDataRemote = Boolean(options.filterRemote);
this.createNewItemFromValueOption = options.createNewItemFromValue;
this.$dropdown = options.$dropdown;
this.$dropdownContainer = this.$dropdown.parent();

View file

@ -118,7 +118,7 @@ export default class CreateMergeRequestDropdown {
this.branchCreated = true;
window.location.href = data.url;
})
.catch(() => Flash('Failed to create a branch for this issue. Please try again.'));
.catch(() => Flash(__('Failed to create a branch for this issue. Please try again.')));
}
createMergeRequest() {
@ -130,7 +130,7 @@ export default class CreateMergeRequestDropdown {
this.mergeRequestCreated = true;
window.location.href = data.url;
})
.catch(() => Flash('Failed to create Merge Request. Please try again.'));
.catch(() => Flash(__('Failed to create Merge Request. Please try again.')));
}
disable() {
@ -227,7 +227,7 @@ export default class CreateMergeRequestDropdown {
.catch(() => {
this.unavailable();
this.disable();
new Flash('Failed to get ref.');
new Flash(__('Failed to get ref.'));
this.isGettingRef = false;

View file

@ -1,59 +0,0 @@
<script>
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
import iconCommit from '../svg/icon_commit.svg';
import limitWarning from './limit_warning_component.vue';
import totalTime from './total_time_component.vue';
export default {
components: {
userAvatarImage,
totalTime,
limitWarning,
},
props: {
items: {
type: Array,
default: () => [],
},
stage: {
type: Object,
default: () => ({}),
},
},
computed: {
iconCommit() {
return iconCommit;
},
},
};
</script>
<template>
<div>
<div class="events-description">
{{ stage.description }}
<limit-warning :count="items.length" />
</div>
<ul class="stage-event-list">
<li v-for="(commit, i) in items" :key="i" class="stage-event-item">
<div class="item-details item-conmmit-component">
<!-- FIXME: Pass an alt attribute here for accessibility -->
<user-avatar-image :img-src="commit.author.avatarUrl" />
<h5 class="item-title commit-title">
<a :href="commit.commitUrl"> {{ commit.title }} </a>
</h5>
<span>
{{ s__('FirstPushedBy|First') }} <span class="commit-icon" v-html="iconCommit"> </span>
<a :href="commit.commitUrl" class="commit-hash-link commit-sha">{{
commit.shortSha
}}</a>
{{ s__('FirstPushedBy|pushed by') }}
<a :href="commit.author.webUrl" class="commit-author-link">
{{ commit.author.name }}
</a>
</span>
</div>
<div class="item-time"><total-time :time="commit.totalTime" /></div>
</li>
</ul>
</div>
</template>

View file

@ -5,7 +5,6 @@ import Flash from '../flash';
import Translate from '../vue_shared/translate';
import banner from './components/banner.vue';
import stageCodeComponent from './components/stage_code_component.vue';
import stagePlanComponent from './components/stage_plan_component.vue';
import stageComponent from './components/stage_component.vue';
import stageReviewComponent from './components/stage_review_component.vue';
import stageStagingComponent from './components/stage_staging_component.vue';
@ -26,7 +25,7 @@ export default () => {
components: {
banner,
'stage-issue-component': stageComponent,
'stage-plan-component': stagePlanComponent,
'stage-plan-component': stageComponent,
'stage-code-component': stageCodeComponent,
'stage-test-component': stageTestComponent,
'stage-review-component': stageReviewComponent,

View file

@ -69,6 +69,16 @@ export default {
required: false,
default: false,
},
dismissEndpoint: {
type: String,
required: false,
default: '',
},
showSuggestPopover: {
type: Boolean,
required: false,
default: false,
},
},
data() {
const treeWidth =
@ -141,7 +151,12 @@ export default {
showTreeList: 'adjustView',
},
mounted() {
this.setBaseConfig({ endpoint: this.endpoint, projectPath: this.projectPath });
this.setBaseConfig({
endpoint: this.endpoint,
projectPath: this.projectPath,
dismissEndpoint: this.dismissEndpoint,
showSuggestPopover: this.showSuggestPopover,
});
if (this.shouldShow) {
this.fetchData();
@ -157,10 +172,12 @@ export default {
this.adjustView();
eventHub.$once('fetchedNotesData', this.setDiscussions);
eventHub.$once('fetchDiffData', this.fetchData);
eventHub.$on('refetchDiffData', this.refetchDiffData);
this.CENTERED_LIMITED_CONTAINER_CLASSES = CENTERED_LIMITED_CONTAINER_CLASSES;
},
beforeDestroy() {
eventHub.$off('fetchDiffData', this.fetchData);
eventHub.$off('refetchDiffData', this.refetchDiffData);
this.removeEventListeners();
},
methods: {
@ -175,10 +192,16 @@ export default {
'scrollToFile',
'toggleShowTreeList',
]),
fetchData() {
refetchDiffData() {
this.assignedDiscussions = false;
this.fetchData(false);
},
fetchData(toggleTree = true) {
this.fetchDiffFiles()
.then(() => {
if (toggleTree) {
this.hideTreeListIfJustOneFile();
}
requestIdleCallback(
() => {

View file

@ -69,7 +69,7 @@ export default {
:link-href="authorUrl"
:img-src="authorAvatar"
:img-alt="authorName"
:img-size="36"
:img-size="40"
class="avatar-cell d-none d-sm-block"
/>
<div class="commit-detail flex-list">
@ -91,7 +91,7 @@ export default {
<icon :size="12" name="ellipsis_h" />
</button>
<div class="commiter">
<div class="committer">
<a
:href="authorUrl"
:class="authorClass"

View file

@ -8,6 +8,7 @@ import NotDiffableViewer from '~/vue_shared/components/diff_viewer/viewers/not_d
import NoPreviewViewer from '~/vue_shared/components/diff_viewer/viewers/no_preview.vue';
import InlineDiffView from './inline_diff_view.vue';
import ParallelDiffView from './parallel_diff_view.vue';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import NoteForm from '../../notes/components/note_form.vue';
import ImageDiffOverlay from './image_diff_overlay.vue';
import DiffDiscussions from './diff_discussions.vue';
@ -26,6 +27,7 @@ export default {
ImageDiffOverlay,
NotDiffableViewer,
NoPreviewViewer,
userAvatarLink,
DiffFileDrafts: () => import('ee_component/batch_comments/components/diff_file_drafts.vue'),
},
mixins: [diffLineNoteFormMixin, draftCommentsMixin],
@ -47,7 +49,7 @@ export default {
}),
...mapGetters('diffs', ['isInlineView', 'isParallelView']),
...mapGetters('diffs', ['getCommentFormForDiffFile']),
...mapGetters(['getNoteableData', 'noteableType']),
...mapGetters(['getNoteableData', 'noteableType', 'getUserData']),
diffMode() {
return getDiffMode(this.diffFile);
},
@ -72,6 +74,9 @@ export default {
diffFileHash() {
return this.diffFile.file_hash;
},
author() {
return this.getUserData;
},
},
methods: {
...mapActions('diffs', ['saveDiffDiscussion', 'closeDiffFileCommentForm']),
@ -134,6 +139,14 @@ export default {
:can-comment="getNoteableData.current_user.can_create_note"
/>
<div v-if="showNotesContainer" class="note-container">
<user-avatar-link
v-if="diffFileCommentForm && author"
:link-href="author.path"
:img-src="author.avatar_url"
:img-alt="author.name"
:img-size="40"
class="d-none d-sm-block new-comment"
/>
<diff-discussions
v-if="diffFile.discussions.length"
class="diff-file-discussions"

View file

@ -240,7 +240,7 @@ export default {
css-class="btn-default btn-transparent btn-clipboard"
/>
<small v-if="isModeChanged" ref="fileMode">
<small v-if="isModeChanged" ref="fileMode" class="mr-1">
{{ diffFile.a_mode }} {{ diffFile.b_mode }}
</small>
@ -254,16 +254,17 @@ export default {
<diff-stats :added-lines="diffFile.added_lines" :removed-lines="diffFile.removed_lines" />
<div class="btn-group" role="group">
<template v-if="diffFile.blob && diffFile.blob.readable_text">
<button
<span v-gl-tooltip.hover :title="s__('MergeRequests|Toggle comments for this file')">
<gl-button
:disabled="!diffHasDiscussions(diffFile)"
:class="{ active: hasExpandedDiscussions }"
:title="s__('MergeRequests|Toggle comments for this file')"
class="js-btn-vue-toggle-comments btn"
type="button"
@click="handleToggleDiscussions"
>
<icon name="comment" />
</button>
</gl-button>
</span>
<edit-button
v-if="!diffFile.deleted_file"

View file

@ -86,7 +86,6 @@ export default {
:key="note.id"
:img-src="note.author.avatar_url"
:tooltip-text="getTooltipText(note)"
:size="19"
class="diff-comment-avatar js-diff-comment-avatar"
@click.native="toggleDiscussions"
/>

View file

@ -4,11 +4,13 @@ import { s__ } from '~/locale';
import diffLineNoteFormMixin from 'ee_else_ce/notes/mixins/diff_line_note_form';
import noteForm from '../../notes/components/note_form.vue';
import autosave from '../../notes/mixins/autosave';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import { DIFF_NOTE_TYPE } from '../constants';
export default {
components: {
noteForm,
userAvatarLink,
},
mixins: [autosave, diffLineNoteFormMixin],
props: {
@ -40,8 +42,18 @@ export default {
noteableData: state => state.notes.noteableData,
diffViewType: state => state.diffs.diffViewType,
}),
...mapState('diffs', ['showSuggestPopover']),
...mapGetters('diffs', ['getDiffFileByHash']),
...mapGetters(['isLoggedIn', 'noteableType', 'getNoteableData', 'getNotesDataByProp']),
...mapGetters([
'isLoggedIn',
'noteableType',
'getNoteableData',
'getNotesDataByProp',
'getUserData',
]),
author() {
return this.getUserData;
},
formData() {
return {
noteableData: this.noteableData,
@ -69,7 +81,12 @@ export default {
}
},
methods: {
...mapActions('diffs', ['cancelCommentForm', 'assignDiscussionsToDiff', 'saveDiffDiscussion']),
...mapActions('diffs', [
'cancelCommentForm',
'assignDiscussionsToDiff',
'saveDiffDiscussion',
'setSuggestPopoverDismissed',
]),
handleCancelCommentForm(shouldConfirm, isDirty) {
if (shouldConfirm && isDirty) {
const msg = s__('Notes|Are you sure you want to cancel creating this comment?');
@ -99,6 +116,14 @@ export default {
<template>
<div class="content discussion-form discussion-form-container discussion-notes">
<user-avatar-link
v-if="author"
:link-href="author.path"
:img-src="author.avatar_url"
:img-alt="author.name"
:img-size="40"
class="d-none d-sm-block"
/>
<note-form
ref="noteForm"
:is-editing="true"
@ -106,11 +131,13 @@ export default {
:line="line"
:help-page-path="helpPagePath"
:diff-file="diffFile"
:show-suggest-popover="showSuggestPopover"
save-button-title="Comment"
class="diff-comment-form"
@handleFormUpdateAddToReview="addToReview"
@cancelForm="handleCancelCommentForm"
@handleFormUpdate="handleSaveNote"
@handleSuggestDismissed="setSuggestPopoverDismissed"
/>
</div>
</template>

View file

@ -38,7 +38,7 @@ export default {
<template>
<gl-button
v-gl-tooltip.bottom
v-gl-tooltip.top
:href="editPath"
:title="__('Edit file')"
class="js-edit-blob"

View file

@ -1,6 +1,7 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlTooltipDirective } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowStats from './file_row_stats.vue';
@ -57,6 +58,9 @@ export default {
this.search = '';
},
},
searchPlaceholder: sprintf(s__('MergeRequest|Filter files or search with %{modifier_key}+p'), {
modifier_key: /Mac/i.test(navigator.userAgent) ? 'cmd' : 'ctrl',
}),
};
</script>
@ -65,10 +69,13 @@ export default {
<div class="append-bottom-8 position-relative tree-list-search d-flex">
<div class="flex-fill d-flex">
<icon name="search" class="position-absolute tree-list-icon" />
<label for="diff-tree-search" class="sr-only">{{ $options.searchPlaceholder }}</label>
<input
id="diff-tree-search"
v-model="search"
:placeholder="s__('MergeRequest|Filter files')"
:placeholder="$options.searchPlaceholder"
type="search"
name="diff-tree-search"
class="form-control"
/>
<button

View file

@ -72,6 +72,8 @@ export default function initDiffsApp(store) {
currentUser: JSON.parse(dataset.currentUserData) || {},
changesEmptyStateIllustration: dataset.changesEmptyStateIllustration,
isFluidLayout: parseBoolean(dataset.isFluidLayout),
dismissEndpoint: dataset.dismissEndpoint,
showSuggestPopover: parseBoolean(dataset.showSuggestPopover),
};
},
computed: {
@ -99,6 +101,8 @@ export default function initDiffsApp(store) {
shouldShow: this.activeTab === 'diffs',
changesEmptyStateIllustration: this.changesEmptyStateIllustration,
isFluidLayout: this.isFluidLayout,
dismissEndpoint: this.dismissEndpoint,
showSuggestPopover: this.showSuggestPopover,
},
});
},

View file

@ -36,8 +36,8 @@ import {
import { diffViewerModes } from '~/ide/constants';
export const setBaseConfig = ({ commit }, options) => {
const { endpoint, projectPath } = options;
commit(types.SET_BASE_CONFIG, { endpoint, projectPath });
const { endpoint, projectPath, dismissEndpoint, showSuggestPopover } = options;
commit(types.SET_BASE_CONFIG, { endpoint, projectPath, dismissEndpoint, showSuggestPopover });
};
export const fetchDiffFiles = ({ state, commit }) => {
@ -52,7 +52,7 @@ export const fetchDiffFiles = ({ state, commit }) => {
});
return axios
.get(state.endpoint, { params: { w: state.showWhitespace ? null : '1' } })
.get(mergeUrlParams({ w: state.showWhitespace ? '0' : '1' }, state.endpoint))
.then(res => {
commit(types.SET_LOADING, false);
commit(types.SET_MERGE_REQUEST_DIFFS, res.data.merge_request_diffs || []);
@ -125,7 +125,8 @@ export const startRenderDiffsQueue = ({ state, commit }) => {
new Promise(resolve => {
const nextFile = state.diffFiles.find(
file =>
!file.renderIt && (!file.viewer.collapsed || !file.viewer.name === diffViewerModes.text),
!file.renderIt &&
(file.viewer && (!file.viewer.collapsed || !file.viewer.name === diffViewerModes.text)),
);
if (nextFile) {
@ -210,11 +211,12 @@ export const scrollToLineIfNeededParallel = (_, line) => {
}
};
export const loadCollapsedDiff = ({ commit, getters }, file) =>
export const loadCollapsedDiff = ({ commit, getters, state }, file) =>
axios
.get(file.load_collapsed_diff_url, {
params: {
commit_id: getters.commitId,
w: state.showWhitespace ? '0' : '1',
},
})
.then(res => {
@ -315,8 +317,10 @@ export const setShowWhitespace = ({ commit }, { showWhitespace, pushState = fals
localStorage.setItem(WHITESPACE_STORAGE_KEY, showWhitespace);
if (pushState) {
historyPushState(showWhitespace ? '?w=0' : '?w=1');
historyPushState(mergeUrlParams({ w: showWhitespace ? '0' : '1' }, window.location.href));
}
eventHub.$emit('refetchDiffData');
};
export const toggleFileFinder = ({ commit }, visible) => {
@ -451,5 +455,17 @@ export const toggleFullDiff = ({ dispatch, getters, state }, filePath) => {
export const setFileCollapsed = ({ commit }, { filePath, collapsed }) =>
commit(types.SET_FILE_COLLAPSED, { filePath, collapsed });
export const setSuggestPopoverDismissed = ({ commit, state }) =>
axios
.post(state.dismissEndpoint, {
feature_name: 'suggest_popover_dismissed',
})
.then(() => {
commit(types.SET_SHOW_SUGGEST_POPOVER);
})
.catch(() => {
createFlash(s__('MergeRequest|Error dismissing suggestion popover. Please try again.'));
});
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};

View file

@ -28,4 +28,6 @@ export default () => ({
renderTreeList: true,
showWhitespace: true,
fileFinderVisible: false,
dismissEndpoint: '',
showSuggestPopover: true,
});

View file

@ -33,3 +33,5 @@ export const SET_HIDDEN_VIEW_DIFF_FILE_LINES = 'SET_HIDDEN_VIEW_DIFF_FILE_LINES'
export const SET_CURRENT_VIEW_DIFF_FILE_LINES = 'SET_CURRENT_VIEW_DIFF_FILE_LINES';
export const ADD_CURRENT_VIEW_DIFF_FILE_LINES = 'ADD_CURRENT_VIEW_DIFF_FILE_LINES';
export const TOGGLE_DIFF_FILE_RENDERING_MORE = 'TOGGLE_DIFF_FILE_RENDERING_MORE';
export const SET_SHOW_SUGGEST_POPOVER = 'SET_SHOW_SUGGEST_POPOVER';

View file

@ -11,8 +11,8 @@ import * as types from './mutation_types';
export default {
[types.SET_BASE_CONFIG](state, options) {
const { endpoint, projectPath } = options;
Object.assign(state, { endpoint, projectPath });
const { endpoint, projectPath, dismissEndpoint, showSuggestPopover } = options;
Object.assign(state, { endpoint, projectPath, dismissEndpoint, showSuggestPopover });
},
[types.SET_LOADING](state, isLoading) {
@ -302,4 +302,7 @@ export default {
file.renderingLines = !file.renderingLines;
},
[types.SET_SHOW_SUGGEST_POPOVER](state) {
state.showSuggestPopover = false;
},
};

View file

@ -21,10 +21,15 @@ class DirtySubmitForm {
}
registerListeners() {
const throttledUpdateDirtyInput = _.throttle(
event => this.updateDirtyInput(event),
DirtySubmitForm.THROTTLE_DURATION,
const getThrottledHandlerForInput = _.memoize(() =>
_.throttle(event => this.updateDirtyInput(event), DirtySubmitForm.THROTTLE_DURATION),
);
const throttledUpdateDirtyInput = event => {
const throttledHandler = getThrottledHandlerForInput(event.target.name);
throttledHandler(event);
};
this.form.addEventListener('input', throttledUpdateDirtyInput);
this.form.addEventListener('change', throttledUpdateDirtyInput);
$(this.form).on('change.select2', throttledUpdateDirtyInput);

View file

@ -4,6 +4,7 @@ import _ from 'underscore';
import './behaviors/preview_markdown';
import csrf from './lib/utils/csrf';
import axios from './lib/utils/axios_utils';
import { n__, __ } from '~/locale';
Dropzone.autoDiscover = false;
@ -90,7 +91,7 @@ export default function dropzoneInput(form) {
if (!processingFileCount) $attachButton.removeClass('hide');
addFileToForm(response.link.url);
},
error: (file, errorMessage = 'Attaching the file failed.', xhr) => {
error: (file, errorMessage = __('Attaching the file failed.'), xhr) => {
// If 'error' event is fired by dropzone, the second parameter is error message.
// If the 'errorMessage' parameter is empty, the default error message is set.
// If the 'error' event is fired by backend (xhr) error response, the third parameter is
@ -273,19 +274,11 @@ export default function dropzoneInput(form) {
};
updateAttachingMessage = (files, messageContainer) => {
let attachingMessage;
const filesCount = files.filter(file => file.status === 'uploading' || file.status === 'queued')
.length;
const attachingMessage = n__('Attaching a file', 'Attaching %d files', filesCount);
// Dinamycally change uploading files text depending on files number in
// dropzone files queue.
if (filesCount > 1) {
attachingMessage = `Attaching ${filesCount} files -`;
} else {
attachingMessage = 'Attaching a file -';
}
messageContainer.text(attachingMessage);
messageContainer.text(`${attachingMessage} -`);
};
form.find('.markdown-selector').click(function onMarkdownClick(e) {

View file

@ -1,10 +1,11 @@
import { __ } from '~/locale';
import emojiRegex from 'emoji-regex';
import InputValidator from '../validators/input_validator';
const invalidInputClass = 'gl-field-error-outline';
export default class NoEmojiValidator {
export default class NoEmojiValidator extends InputValidator {
constructor(opts = {}) {
super();
const container = opts.container || '';
this.noEmojiEmelents = document.querySelectorAll(`${container} .js-block-emoji`);
@ -19,45 +20,14 @@ export default class NoEmojiValidator {
const { value } = this.inputDomElement;
this.errorMessage = __('Invalid input, please avoid emojis');
this.validatePattern(value);
this.setValidationStateAndMessage();
}
validatePattern(value) {
const pattern = emojiRegex();
this.hasEmojis = new RegExp(pattern).test(value);
if (this.hasEmojis) {
this.inputDomElement.setCustomValidity(__('Invalid input, please avoid emojis'));
} else {
this.inputDomElement.setCustomValidity('');
}
}
setValidationStateAndMessage() {
if (!this.inputDomElement.checkValidity()) {
this.setInvalidState();
} else {
this.clearFieldValidationState();
}
}
clearFieldValidationState() {
this.inputDomElement.classList.remove(invalidInputClass);
this.inputErrorMessage.classList.add('hide');
}
setInvalidState() {
this.inputDomElement.classList.add(invalidInputClass);
this.setErrorMessage();
}
setErrorMessage() {
if (this.hasEmojis) {
this.inputErrorMessage.innerHTML = this.inputDomElement.validationMessage;
} else {
this.inputErrorMessage.innerHTML = this.inputDomElement.title;
}
this.inputErrorMessage.classList.remove('hide');
this.invalidInput = new RegExp(pattern).test(value);
}
}

View file

@ -1,6 +1,6 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import TablePagination from '~/vue_shared/components/table_pagination.vue';
import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
import containerMixin from 'ee_else_ce/environments/mixins/container_mixin';
import EnvironmentTable from '../components/environments_table.vue';

View file

@ -11,7 +11,7 @@ import Flash from '../../flash';
import eventHub from '../event_hub';
import EnvironmentsService from '../services/environments_service';
import tablePagination from '../../vue_shared/components/table_pagination.vue';
import tablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
import environmentTable from '../components/environments_table.vue';
import tabs from '../../vue_shared/components/navigation_tabs.vue';
import container from '../components/container.vue';

View file

@ -2,10 +2,10 @@ import _ from 'underscore';
import { __, s__, sprintf } from '~/locale';
import { getDisplayName } from '../utils';
export const hasProjects = state => !!state.projects && state.projects.length > 0;
export const hasProjects = state => Boolean(state.projects) && state.projects.length > 0;
export const isProjectInvalid = (state, getters) =>
!!state.selectedProject &&
Boolean(state.selectedProject) &&
getters.hasProjects &&
!state.projects.some(project => _.isMatch(state.selectedProject, project));

View file

@ -8,9 +8,19 @@ import DropdownUtils from './dropdown_utils';
import { mergeUrlParams } from '../lib/utils/url_utility';
export default class AvailableDropdownMappings {
constructor(container, baseEndpoint, groupsOnly, includeAncestorGroups, includeDescendantGroups) {
constructor(
container,
baseEndpoint,
labelsEndpoint,
milestonesEndpoint,
groupsOnly,
includeAncestorGroups,
includeDescendantGroups,
) {
this.container = container;
this.baseEndpoint = baseEndpoint;
this.labelsEndpoint = labelsEndpoint;
this.milestonesEndpoint = milestonesEndpoint;
this.groupsOnly = groupsOnly;
this.includeAncestorGroups = includeAncestorGroups;
this.includeDescendantGroups = includeDescendantGroups;
@ -117,11 +127,11 @@ export default class AvailableDropdownMappings {
}
getMilestoneEndpoint() {
return `${this.baseEndpoint}/milestones.json`;
return `${this.milestonesEndpoint}.json`;
}
getLabelsEndpoint() {
let endpoint = `${this.baseEndpoint}/labels.json?`;
let endpoint = `${this.labelsEndpoint}.json?`;
if (this.groupsOnly) {
endpoint = `${endpoint}only_group_labels=true&`;

View file

@ -0,0 +1,2 @@
/* eslint-disable import/prefer-default-export */
export const TOKEN_TYPES = ['author', 'assignee'];

View file

@ -18,6 +18,7 @@ export default class DropdownUser extends DropdownAjaxFilter {
group_id: this.getGroupId(),
project_id: this.getProjectId(),
current_user: true,
...this.projectOrGroupId(),
},
onLoadingFinished: () => {
this.hideCurrentUser();
@ -36,4 +37,17 @@ export default class DropdownUser extends DropdownAjaxFilter {
getProjectId() {
return this.input.getAttribute('data-project-id');
}
projectOrGroupId() {
const projectId = this.getProjectId();
const groupId = this.getGroupId();
if (groupId) {
return {
group_id: groupId,
};
}
return {
project_id: projectId,
};
}
}

Some files were not shown because too many files have changed in this diff Show more