New upstream version 11.1.8+dfsg

This commit is contained in:
Pirate Praveen 2018-11-08 19:23:39 +05:30
parent 4d97b13529
commit ecad3f3e66
4181 changed files with 120348 additions and 80018 deletions

View file

@ -8,8 +8,6 @@ engines:
languages: languages:
- ruby - ruby
- javascript - javascript
exclude_paths:
- "lib/api/v3/*"
ratings: ratings:
paths: paths:
- Gemfile.lock - Gemfile.lock

View file

@ -1,56 +0,0 @@
{
"env": {
"browser": true,
"es6": true
},
"extends": [
"airbnb-base",
"plugin:vue/recommended"
],
"globals": {
"__webpack_public_path__": true,
"gl": false,
"gon": false,
"localStorage": false
},
"parserOptions": {
"parser": "babel-eslint"
},
"plugins": [
"filenames",
"import",
"html",
"promise"
],
"settings": {
"html/html-extensions": [".html", ".html.raw"],
"import/resolver": {
"webpack": {
"config": "./config/webpack.config.js"
}
}
},
"rules": {
"filenames/match-regex": [2, "^[a-z0-9_]+$"],
"import/no-commonjs": "error",
"no-multiple-empty-lines": ["error", { "max": 1 }],
"promise/catch-or-return": "error",
"no-underscore-dangle": ["error", { "allow": ["__", "_links"] }],
"no-mixed-operators": 0,
"space-before-function-paren": 0,
"curly": 0,
"arrow-parens": 0,
"vue/html-self-closing": [
"error",
{
"html": {
"void": "always",
"normal": "never",
"component": "always"
},
"svg": "always",
"math": "always"
}
]
}
}

71
.eslintrc.yml Normal file
View file

@ -0,0 +1,71 @@
---
env:
browser: true
es6: true
extends:
- airbnb-base
- plugin:vue/recommended
globals:
__webpack_public_path__: true
gl: false
gon: false
localStorage: false
parserOptions:
parser: babel-eslint
plugins:
- filenames
- import
- html
- promise
settings:
html/html-extensions:
- ".html"
- ".html.raw"
import/resolver:
webpack:
config: "./config/webpack.config.js"
rules:
filenames/match-regex:
- error
- "^[a-z0-9_]+$"
import/no-commonjs: error
no-multiple-empty-lines:
- error
- max: 1
promise/catch-or-return: error
no-underscore-dangle:
- error
- allow:
- __
- _links
no-mixed-operators: off
vue/html-self-closing:
- error
- html:
void: always
normal: never
component: always
svg: always
math: always
## Conflicting rules with prettier:
space-before-function-paren: off
curly: off
arrow-parens: off
function-paren-newline: off
object-curly-newline: off
padded-blocks: off
# Disabled for now, to make the eslint 3 -> eslint 4 update smoother
## Indent rule. We are using the old for now: https://eslint.org/docs/user-guide/migrating-to-4.0.0#indent-rewrite
indent: off
indent-legacy:
- error
- 2
- SwitchCase: 1
VariableDeclarator: 1
outerIIFEBody: 1
FunctionDeclaration:
parameters: 1
body: 1
FunctionExpression:
parameters: 1
body: 1

View file

@ -1,12 +1,34 @@
*.erb *.erb
lib/gitlab/sanitizers/svg/whitelist.rb lib/gitlab/sanitizers/svg/whitelist.rb
lib/gitlab/diff/position_tracer.rb lib/gitlab/diff/position_tracer.rb
app/controllers/projects/approver_groups_controller.rb
app/controllers/projects/approvers_controller.rb
app/controllers/projects/protected_branches/merge_access_levels_controller.rb
app/controllers/projects/protected_branches/push_access_levels_controller.rb
app/controllers/projects/protected_tags/create_access_levels_controller.rb
app/policies/project_policy.rb app/policies/project_policy.rb
app/models/concerns/relative_positioning.rb app/models/concerns/relative_positioning.rb
app/workers/stuck_merge_jobs_worker.rb app/workers/stuck_merge_jobs_worker.rb
lib/gitlab/redis/*.rb lib/gitlab/redis/*.rb
lib/gitlab/gitaly_client/operation_service.rb lib/gitlab/gitaly_client/operation_service.rb
app/models/project_services/packagist_service.rb
lib/gitlab/background_migration/normalize_ldap_extern_uids_range.rb
lib/gitlab/background_migration/* lib/gitlab/background_migration/*
app/models/project_services/kubernetes_service.rb app/models/project_services/kubernetes_service.rb
lib/gitlab/workhorse.rb lib/gitlab/workhorse.rb
lib/gitlab/ci/trace/chunked_io.rb lib/gitlab/ci/trace/chunked_io.rb
lib/gitlab/gitaly_client/ref_service.rb
lib/gitlab/gitaly_client/commit_service.rb
lib/gitlab/git/commit.rb
lib/gitlab/git/tag.rb
ee/db/**/*
ee/app/serializers/ee/merge_request_widget_entity.rb
ee/lib/api/epics.rb
ee/lib/api/geo_nodes.rb
ee/lib/ee/api/group_boards.rb
ee/lib/ee/api/boards.rb
ee/lib/ee/gitlab/ldap/sync/admin_users.rb
ee/app/workers/geo/file_download_dispatch_worker/job_artifact_job_finder.rb
ee/app/workers/geo/file_download_dispatch_worker/lfs_object_job_finder.rb
ee/spec/**/*

3
.gitignore vendored
View file

@ -29,7 +29,7 @@ eslint-report.html
/app/assets/javascripts/locale/**/app.js /app/assets/javascripts/locale/**/app.js
/backups/* /backups/*
/config/aws.yml /config/aws.yml
/config/database.yml /config/database*.yml
/config/gitlab.yml /config/gitlab.yml
/config/gitlab_ci.yml /config/gitlab_ci.yml
/config/initializers/rack_attack.rb /config/initializers/rack_attack.rb
@ -76,3 +76,4 @@ eslint-report.html
/.rspec /.rspec
/plugins/* /plugins/*
/.gitlab_pages_secret /.gitlab_pages_secret
package-lock.json

View file

@ -1,4 +1,4 @@
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.7-golang-1.9-git-2.17-chrome-65.0-node-8.x-yarn-1.2-postgresql-9.6" image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.4.4-golang-1.9-git-2.17-chrome-67.0-node-8.x-yarn-1.2-postgresql-9.6-graphicsmagick-1.3.29"
.dedicated-runner: &dedicated-runner .dedicated-runner: &dedicated-runner
retry: 1 retry: 1
@ -6,7 +6,7 @@ image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.7-golang-1.9-git
- gitlab-org - gitlab-org
.default-cache: &default-cache .default-cache: &default-cache
key: "ruby-2.3.7-debian-stretch-with-yarn" key: "ruby-2.4.4-debian-stretch-with-yarn"
paths: paths:
- vendor/ruby - vendor/ruby
- .yarn-cache/ - .yarn-cache/
@ -31,7 +31,6 @@ variables:
GIT_SUBMODULE_STRATEGY: "none" GIT_SUBMODULE_STRATEGY: "none"
GET_SOURCES_ATTEMPTS: "3" GET_SOURCES_ATTEMPTS: "3"
KNAPSACK_RSPEC_SUITE_REPORT_PATH: knapsack/${CI_PROJECT_NAME}/rspec_report-master.json KNAPSACK_RSPEC_SUITE_REPORT_PATH: knapsack/${CI_PROJECT_NAME}/rspec_report-master.json
KNAPSACK_SPINACH_SUITE_REPORT_PATH: knapsack/${CI_PROJECT_NAME}/spinach_report-master.json
FLAKY_RSPEC_SUITE_REPORT_PATH: rspec_flaky/report-suite.json FLAKY_RSPEC_SUITE_REPORT_PATH: rspec_flaky/report-suite.json
before_script: before_script:
@ -127,6 +126,23 @@ stages:
<<: *dedicated-no-docs-pull-cache-job <<: *dedicated-no-docs-pull-cache-job
<<: *except-docs-and-qa <<: *except-docs-and-qa
.single-script-job: &single-script-job
image: ruby:2.4-alpine
before_script: []
stage: build
cache: {}
dependencies: []
variables: &single-script-job-variables
GIT_STRATEGY: none
before_script:
# We need to download the script rather than clone the repo since the
# package-and-qa job will not be able to run when the branch gets
# deleted (when merging the MR).
- export SCRIPT_NAME="${SCRIPT_NAME:-$CI_JOB_NAME}"
- apk add --update openssl
- wget $CI_PROJECT_URL/raw/$CI_COMMIT_SHA/scripts/$SCRIPT_NAME
- chmod 755 $SCRIPT_NAME
.rake-exec: &rake-exec .rake-exec: &rake-exec
<<: *dedicated-no-docs-no-db-pull-cache-job <<: *dedicated-no-docs-no-db-pull-cache-job
script: script:
@ -179,46 +195,6 @@ stages:
<<: *rspec-metadata-mysql <<: *rspec-metadata-mysql
<<: *rails5 <<: *rails5
.spinach-metadata: &spinach-metadata
<<: *dedicated-runner
<<: *except-docs-and-qa
<<: *pull-cache
<<: *rails5-variables
stage: test
script:
- JOB_NAME=( $CI_JOB_NAME )
- export CI_NODE_INDEX=${JOB_NAME[-2]}
- export CI_NODE_TOTAL=${JOB_NAME[-1]}
- export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- export KNAPSACK_GENERATE_REPORT=true
- export CACHE_CLASSES=true
- cp ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH}
- scripts/gitaly-test-spawn
- knapsack spinach "-r rerun" -b || retry '[[ -e tmp/spinach-rerun.txt ]] && bundle exec spinach -b -r rerun $(cat tmp/spinach-rerun.txt)'
artifacts:
expire_in: 31d
when: always
paths:
- coverage/
- knapsack/
- tmp/capybara/
.spinach-metadata-pg: &spinach-metadata-pg
<<: *spinach-metadata
<<: *use-pg
.spinach-metadata-pg-rails5: &spinach-metadata-pg-rails5
<<: *spinach-metadata-pg
<<: *rails5
.spinach-metadata-mysql: &spinach-metadata-mysql
<<: *spinach-metadata
<<: *use-mysql
.spinach-metadata-mysql-rails5: &spinach-metadata-mysql-rails5
<<: *spinach-metadata-mysql
<<: *rails5
.only-canonical-masters: &only-canonical-masters .only-canonical-masters: &only-canonical-masters
only: only:
- master@gitlab-org/gitlab-ce - master@gitlab-org/gitlab-ce
@ -230,7 +206,7 @@ stages:
<<: *dedicated-no-docs-and-no-qa-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
<<: *use-pg <<: *use-pg
variables: variables:
CREATE_DB_USER: "true" SETUP_DB: "false"
script: script:
# Manually clone gitlab-test and only seed this project in # Manually clone gitlab-test and only seed this project in
# db/fixtures/development/04_project.rb thanks to SIZE=1 below # db/fixtures/development/04_project.rb thanks to SIZE=1 below
@ -244,27 +220,6 @@ stages:
paths: paths:
- log/development.log - log/development.log
# Review docs base
.review-docs: &review-docs
<<: *dedicated-runner
<<: *except-qa
image: ruby:2.4-alpine
before_script:
- gem install gitlab --no-doc
# We need to download the script rather than clone the repo since the
# review-docs-cleanup job will not be able to run when the branch gets
# deleted (when merging the MR).
- apk add --update openssl
- wget https://gitlab.com/gitlab-org/gitlab-ce/raw/master/scripts/trigger-build-docs
- chmod 755 trigger-build-docs
cache: {}
dependencies: []
variables:
GIT_STRATEGY: none
when: manual
only:
- branches
# DB migration, rollback, and seed jobs # DB migration, rollback, and seed jobs
.db-migrate-reset: &db-migrate-reset .db-migrate-reset: &db-migrate-reset
<<: *dedicated-no-docs-and-no-qa-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
@ -274,7 +229,7 @@ stages:
.migration-paths: &migration-paths .migration-paths: &migration-paths
<<: *dedicated-no-docs-and-no-qa-pull-cache-job <<: *dedicated-no-docs-and-no-qa-pull-cache-job
variables: variables:
CREATE_DB_USER: "true" SETUP_DB: "false"
script: script:
- git fetch https://gitlab.com/gitlab-org/gitlab-ce.git v9.3.0 - git fetch https://gitlab.com/gitlab-org/gitlab-ce.git v9.3.0
- git checkout -f FETCH_HEAD - git checkout -f FETCH_HEAD
@ -283,7 +238,7 @@ stages:
- cp config/gitlab.yml.example config/gitlab.yml - cp config/gitlab.yml.example config/gitlab.yml
- bundle exec rake db:drop db:create db:schema:load db:seed_fu - bundle exec rake db:drop db:create db:schema:load db:seed_fu
- date - date
- git checkout $CI_COMMIT_SHA - git checkout -f $CI_COMMIT_SHA
- bundle install $BUNDLE_INSTALL_FLAGS - bundle install $BUNDLE_INSTALL_FLAGS
- date - date
- . scripts/prepare_build.sh - . scripts/prepare_build.sh
@ -294,50 +249,88 @@ stages:
# Trigger a package build in omnibus-gitlab repository # Trigger a package build in omnibus-gitlab repository
# #
package-and-qa: package-and-qa:
image: ruby:2.4-alpine <<: *single-script-job
before_script: []
stage: build
cache: {}
when: manual
variables: variables:
GIT_STRATEGY: none <<: *single-script-job-variables
SCRIPT_NAME: trigger-build
retry: 0 retry: 0
before_script:
# We need to download the script rather than clone the repo since the
# package-and-qa job will not be able to run when the branch gets
# deleted (when merging the MR).
- apk add --update openssl
- wget https://gitlab.com/$CI_PROJECT_PATH/raw/$CI_COMMIT_SHA/scripts/trigger-build-omnibus
- chmod 755 trigger-build-omnibus
script: script:
- ./trigger-build-omnibus - ./$SCRIPT_NAME omnibus
when: manual
only: only:
- //@gitlab-org/gitlab-ce - //@gitlab-org/gitlab-ce
- //@gitlab-org/gitlab-ee - //@gitlab-org/gitlab-ee
# Trigger a docs build in gitlab-docs # Review docs base
# Useful to preview the docs changes live .review-docs: &review-docs
review-docs-deploy: <<: *dedicated-runner
<<: *review-docs <<: *single-script-job
stage: build variables:
<<: *single-script-job-variables
SCRIPT_NAME: trigger-build-docs
environment: environment:
name: review-docs/$CI_COMMIT_REF_NAME name: review-docs/$CI_COMMIT_REF_SLUG
# DOCS_REVIEW_APPS_DOMAIN and DOCS_GITLAB_REPO_SUFFIX are secret variables # DOCS_REVIEW_APPS_DOMAIN and DOCS_GITLAB_REPO_SUFFIX are secret variables
# Discussion: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14236/diffs#note_40140693 # Discussion: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14236/diffs#note_40140693
url: http://$DOCS_GITLAB_REPO_SUFFIX-$CI_COMMIT_REF_SLUG.$DOCS_REVIEW_APPS_DOMAIN/$DOCS_GITLAB_REPO_SUFFIX url: http://$CI_ENVIRONMENT_SLUG.$DOCS_REVIEW_APPS_DOMAIN/$DOCS_GITLAB_REPO_SUFFIX
on_stop: review-docs-cleanup on_stop: review-docs-cleanup
# Trigger a manual docs build in gitlab-docs only on non docs-only branches.
# Useful to preview the docs changes live.
review-docs-deploy-manual:
<<: *review-docs
stage: build
script: script:
- ./trigger-build-docs deploy - gem install gitlab --no-ri --no-rdoc
- ./$SCRIPT_NAME deploy
when: manual
only:
- branches@gitlab-org/gitlab-ce
- branches@gitlab-org/gitlab-ee
<<: *except-docs-and-qa
# Always trigger a docs build in gitlab-docs only on docs-only branches.
# Useful to preview the docs changes live.
review-docs-deploy:
<<: *review-docs
stage: post-test
script:
- gem install gitlab --no-ri --no-rdoc
- ./$SCRIPT_NAME deploy
only:
- /(^docs[\/-].*|.*-docs$)/@gitlab-org/gitlab-ce
- /(^docs[\/-].*|.*-docs$)/@gitlab-org/gitlab-ee
<<: *except-qa
# Cleanup remote environment of gitlab-docs # Cleanup remote environment of gitlab-docs
review-docs-cleanup: review-docs-cleanup:
<<: *review-docs <<: *review-docs
stage: post-cleanup stage: post-cleanup
environment: environment:
name: review-docs/$CI_COMMIT_REF_NAME name: review-docs/$CI_COMMIT_REF_SLUG
action: stop action: stop
when: manual
script: script:
- ./trigger-build-docs cleanup - gem install gitlab --no-ri --no-rdoc
- ./$SCRIPT_NAME cleanup
##
# Trigger a docker image build in CNG (Cloud Native GitLab) repository
#
cloud-native-image:
image: ruby:2.4-alpine
before_script: []
stage: build
allow_failure: true
variables:
GIT_DEPTH: "1"
cache: {}
script:
- gem install gitlab --no-ri --no-rdoc
- BUILD_TRIGGER_TOKEN=$CI_JOB_TOKEN scripts/trigger-build cng
only:
- tags@gitlab-org/gitlab-ce
- tags@gitlab-org/gitlab-ee
# Retrieve knapsack and rspec_flaky reports # Retrieve knapsack and rspec_flaky reports
retrieve-tests-metadata: retrieve-tests-metadata:
@ -350,9 +343,7 @@ retrieve-tests-metadata:
script: script:
- mkdir -p knapsack/${CI_PROJECT_NAME}/ - mkdir -p knapsack/${CI_PROJECT_NAME}/
- wget -O $KNAPSACK_RSPEC_SUITE_REPORT_PATH http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/$KNAPSACK_RSPEC_SUITE_REPORT_PATH || rm $KNAPSACK_RSPEC_SUITE_REPORT_PATH - wget -O $KNAPSACK_RSPEC_SUITE_REPORT_PATH http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/$KNAPSACK_RSPEC_SUITE_REPORT_PATH || rm $KNAPSACK_RSPEC_SUITE_REPORT_PATH
- wget -O $KNAPSACK_SPINACH_SUITE_REPORT_PATH http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/$KNAPSACK_SPINACH_SUITE_REPORT_PATH || rm $KNAPSACK_SPINACH_SUITE_REPORT_PATH
- '[[ -f $KNAPSACK_RSPEC_SUITE_REPORT_PATH ]] || echo "{}" > ${KNAPSACK_RSPEC_SUITE_REPORT_PATH}' - '[[ -f $KNAPSACK_RSPEC_SUITE_REPORT_PATH ]] || echo "{}" > ${KNAPSACK_RSPEC_SUITE_REPORT_PATH}'
- '[[ -f $KNAPSACK_SPINACH_SUITE_REPORT_PATH ]] || echo "{}" > ${KNAPSACK_SPINACH_SUITE_REPORT_PATH}'
- mkdir -p rspec_flaky/ - mkdir -p rspec_flaky/
- wget -O $FLAKY_RSPEC_SUITE_REPORT_PATH http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/$FLAKY_RSPEC_SUITE_REPORT_PATH || rm $FLAKY_RSPEC_SUITE_REPORT_PATH - wget -O $FLAKY_RSPEC_SUITE_REPORT_PATH http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/$FLAKY_RSPEC_SUITE_REPORT_PATH || rm $FLAKY_RSPEC_SUITE_REPORT_PATH
- '[[ -f $FLAKY_RSPEC_SUITE_REPORT_PATH ]] || echo "{}" > ${FLAKY_RSPEC_SUITE_REPORT_PATH}' - '[[ -f $FLAKY_RSPEC_SUITE_REPORT_PATH ]] || echo "{}" > ${FLAKY_RSPEC_SUITE_REPORT_PATH}'
@ -368,12 +359,11 @@ update-tests-metadata:
- rspec_flaky/ - rspec_flaky/
policy: push policy: push
script: script:
- retry gem install fog-aws mime-types activesupport - retry gem install fog-aws mime-types activesupport --no-ri --no-rdoc
- 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
- scripts/merge-reports ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/spinach-pg_node_*.json
- scripts/merge-reports ${FLAKY_RSPEC_SUITE_REPORT_PATH} rspec_flaky/all_*_*.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} - 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 $KNAPSACK_SPINACH_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' - '[[ -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 knapsack/${CI_PROJECT_NAME}/*_node_*.json
- rm -f rspec_flaky/all_*.json rspec_flaky/new_*.json - rm -f rspec_flaky/all_*.json rspec_flaky/new_*.json
@ -417,7 +407,11 @@ compile-assets:
- date - date
- yarn install --frozen-lockfile --cache-folder .yarn-cache - yarn install --frozen-lockfile --cache-folder .yarn-cache
- date - date
- free -m
- bundle exec rake gitlab:assets:compile - bundle exec rake gitlab:assets:compile
variables:
# we override the max_old_space_size to prevent OOM errors
NODE_OPTIONS: --max_old_space_size=3584
artifacts: artifacts:
expire_in: 7d expire_in: 7d
paths: paths:
@ -434,6 +428,7 @@ setup-test-env:
script: script:
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init' - bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
- scripts/gitaly-test-build # Do not use 'bundle exec' here - scripts/gitaly-test-build # Do not use 'bundle exec' here
- BUNDLE_GEMFILE=Gemfile.rails5 bundle install $BUNDLE_INSTALL_FLAGS
artifacts: artifacts:
expire_in: 7d expire_in: 7d
paths: paths:
@ -441,133 +436,129 @@ setup-test-env:
- config/secrets.yml - config/secrets.yml
- vendor/gitaly-ruby - vendor/gitaly-ruby
rspec-pg 0 28: *rspec-metadata-pg rspec-pg 0 30: *rspec-metadata-pg
rspec-pg 1 28: *rspec-metadata-pg rspec-pg 1 30: *rspec-metadata-pg
rspec-pg 2 28: *rspec-metadata-pg rspec-pg 2 30: *rspec-metadata-pg
rspec-pg 3 28: *rspec-metadata-pg rspec-pg 3 30: *rspec-metadata-pg
rspec-pg 4 28: *rspec-metadata-pg rspec-pg 4 30: *rspec-metadata-pg
rspec-pg 5 28: *rspec-metadata-pg rspec-pg 5 30: *rspec-metadata-pg
rspec-pg 6 28: *rspec-metadata-pg rspec-pg 6 30: *rspec-metadata-pg
rspec-pg 7 28: *rspec-metadata-pg rspec-pg 7 30: *rspec-metadata-pg
rspec-pg 8 28: *rspec-metadata-pg rspec-pg 8 30: *rspec-metadata-pg
rspec-pg 9 28: *rspec-metadata-pg rspec-pg 9 30: *rspec-metadata-pg
rspec-pg 10 28: *rspec-metadata-pg rspec-pg 10 30: *rspec-metadata-pg
rspec-pg 11 28: *rspec-metadata-pg rspec-pg 11 30: *rspec-metadata-pg
rspec-pg 12 28: *rspec-metadata-pg rspec-pg 12 30: *rspec-metadata-pg
rspec-pg 13 28: *rspec-metadata-pg rspec-pg 13 30: *rspec-metadata-pg
rspec-pg 14 28: *rspec-metadata-pg rspec-pg 14 30: *rspec-metadata-pg
rspec-pg 15 28: *rspec-metadata-pg rspec-pg 15 30: *rspec-metadata-pg
rspec-pg 16 28: *rspec-metadata-pg rspec-pg 16 30: *rspec-metadata-pg
rspec-pg 17 28: *rspec-metadata-pg rspec-pg 17 30: *rspec-metadata-pg
rspec-pg 18 28: *rspec-metadata-pg rspec-pg 18 30: *rspec-metadata-pg
rspec-pg 19 28: *rspec-metadata-pg rspec-pg 19 30: *rspec-metadata-pg
rspec-pg 20 28: *rspec-metadata-pg rspec-pg 20 30: *rspec-metadata-pg
rspec-pg 21 28: *rspec-metadata-pg rspec-pg 21 30: *rspec-metadata-pg
rspec-pg 22 28: *rspec-metadata-pg rspec-pg 22 30: *rspec-metadata-pg
rspec-pg 23 28: *rspec-metadata-pg rspec-pg 23 30: *rspec-metadata-pg
rspec-pg 24 28: *rspec-metadata-pg rspec-pg 24 30: *rspec-metadata-pg
rspec-pg 25 28: *rspec-metadata-pg rspec-pg 25 30: *rspec-metadata-pg
rspec-pg 26 28: *rspec-metadata-pg rspec-pg 26 30: *rspec-metadata-pg
rspec-pg 27 28: *rspec-metadata-pg rspec-pg 27 30: *rspec-metadata-pg
rspec-pg 28 30: *rspec-metadata-pg
rspec-pg 29 30: *rspec-metadata-pg
rspec-mysql 0 28: *rspec-metadata-mysql rspec-mysql 0 30: *rspec-metadata-mysql
rspec-mysql 1 28: *rspec-metadata-mysql rspec-mysql 1 30: *rspec-metadata-mysql
rspec-mysql 2 28: *rspec-metadata-mysql rspec-mysql 2 30: *rspec-metadata-mysql
rspec-mysql 3 28: *rspec-metadata-mysql rspec-mysql 3 30: *rspec-metadata-mysql
rspec-mysql 4 28: *rspec-metadata-mysql rspec-mysql 4 30: *rspec-metadata-mysql
rspec-mysql 5 28: *rspec-metadata-mysql rspec-mysql 5 30: *rspec-metadata-mysql
rspec-mysql 6 28: *rspec-metadata-mysql rspec-mysql 6 30: *rspec-metadata-mysql
rspec-mysql 7 28: *rspec-metadata-mysql rspec-mysql 7 30: *rspec-metadata-mysql
rspec-mysql 8 28: *rspec-metadata-mysql rspec-mysql 8 30: *rspec-metadata-mysql
rspec-mysql 9 28: *rspec-metadata-mysql rspec-mysql 9 30: *rspec-metadata-mysql
rspec-mysql 10 28: *rspec-metadata-mysql rspec-mysql 10 30: *rspec-metadata-mysql
rspec-mysql 11 28: *rspec-metadata-mysql rspec-mysql 11 30: *rspec-metadata-mysql
rspec-mysql 12 28: *rspec-metadata-mysql rspec-mysql 12 30: *rspec-metadata-mysql
rspec-mysql 13 28: *rspec-metadata-mysql rspec-mysql 13 30: *rspec-metadata-mysql
rspec-mysql 14 28: *rspec-metadata-mysql rspec-mysql 14 30: *rspec-metadata-mysql
rspec-mysql 15 28: *rspec-metadata-mysql rspec-mysql 15 30: *rspec-metadata-mysql
rspec-mysql 16 28: *rspec-metadata-mysql rspec-mysql 16 30: *rspec-metadata-mysql
rspec-mysql 17 28: *rspec-metadata-mysql rspec-mysql 17 30: *rspec-metadata-mysql
rspec-mysql 18 28: *rspec-metadata-mysql rspec-mysql 18 30: *rspec-metadata-mysql
rspec-mysql 19 28: *rspec-metadata-mysql rspec-mysql 19 30: *rspec-metadata-mysql
rspec-mysql 20 28: *rspec-metadata-mysql rspec-mysql 20 30: *rspec-metadata-mysql
rspec-mysql 21 28: *rspec-metadata-mysql rspec-mysql 21 30: *rspec-metadata-mysql
rspec-mysql 22 28: *rspec-metadata-mysql rspec-mysql 22 30: *rspec-metadata-mysql
rspec-mysql 23 28: *rspec-metadata-mysql rspec-mysql 23 30: *rspec-metadata-mysql
rspec-mysql 24 28: *rspec-metadata-mysql rspec-mysql 24 30: *rspec-metadata-mysql
rspec-mysql 25 28: *rspec-metadata-mysql rspec-mysql 25 30: *rspec-metadata-mysql
rspec-mysql 26 28: *rspec-metadata-mysql rspec-mysql 26 30: *rspec-metadata-mysql
rspec-mysql 27 28: *rspec-metadata-mysql rspec-mysql 27 30: *rspec-metadata-mysql
rspec-mysql 28 30: *rspec-metadata-mysql
rspec-mysql 29 30: *rspec-metadata-mysql
spinach-pg 0 2: *spinach-metadata-pg rspec-pg-rails5 0 30: *rspec-metadata-pg-rails5
spinach-pg 1 2: *spinach-metadata-pg rspec-pg-rails5 1 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 2 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 3 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 4 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 5 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 6 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 7 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 8 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 9 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 10 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 11 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 12 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 13 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 14 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 15 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 16 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 17 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 18 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 19 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 20 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 21 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 22 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 23 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 24 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 25 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 26 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 27 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 28 30: *rspec-metadata-pg-rails5
rspec-pg-rails5 29 30: *rspec-metadata-pg-rails5
spinach-mysql 0 2: *spinach-metadata-mysql rspec-mysql-rails5 0 30: *rspec-metadata-mysql-rails5
spinach-mysql 1 2: *spinach-metadata-mysql rspec-mysql-rails5 1 30: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 2 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 0 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 3 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 1 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 4 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 2 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 5 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 3 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 6 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 4 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 7 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 5 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 8 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 6 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 9 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 7 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 10 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 8 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 11 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 9 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 12 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 10 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 13 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 11 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 14 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 12 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 15 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 13 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 16 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 14 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 17 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 15 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 18 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 16 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 19 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 17 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 20 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 18 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 21 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 19 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 22 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 20 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 23 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 21 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 24 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 22 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 25 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 23 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 26 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 24 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 27 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 25 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 28 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 26 28: *rspec-metadata-pg-rails5 rspec-mysql-rails5 29 30: *rspec-metadata-mysql-rails5
rspec-pg-rails5 27 28: *rspec-metadata-pg-rails5
rspec-mysql-rails5 0 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 1 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 2 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 3 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 4 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 5 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 6 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 7 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 8 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 9 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 10 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 11 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 12 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 13 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 14 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 15 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 16 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 17 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 18 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 19 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 20 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 21 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 22 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 23 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 24 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 25 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 26 28: *rspec-metadata-mysql-rails5
rspec-mysql-rails5 27 28: *rspec-metadata-mysql-rails5
spinach-pg-rails5 0 2: *spinach-metadata-pg-rails5
spinach-pg-rails5 1 2: *spinach-metadata-pg-rails5
spinach-mysql-rails5 0 2: *spinach-metadata-mysql-rails5
spinach-mysql-rails5 1 2: *spinach-metadata-mysql-rails5
static-analysis: static-analysis:
<<: *dedicated-no-docs-no-db-pull-cache-job <<: *dedicated-no-docs-no-db-pull-cache-job
@ -577,7 +568,7 @@ static-analysis:
script: script:
- scripts/static-analysis - scripts/static-analysis
cache: cache:
key: "ruby-2.3.7-debian-stretch-with-yarn-and-rubocop" key: "ruby-2.4.4-debian-stretch-with-yarn-and-rubocop"
paths: paths:
- vendor/ruby - vendor/ruby
- .yarn-cache/ - .yarn-cache/
@ -613,12 +604,18 @@ downtime_check:
- /(^docs[\/-].*|.*-docs$)/ - /(^docs[\/-].*|.*-docs$)/
- /(^qa[\/-].*|.*-qa$)/ - /(^qa[\/-].*|.*-qa$)/
rails5_gemfile_lock_check:
<<: *dedicated-no-docs-no-db-pull-cache-job
<<: *except-docs-and-qa
script:
- scripts/rails5-gemfile-lock-check
ee_compat_check: ee_compat_check:
<<: *rake-exec <<: *rake-exec
except: except:
- master - master
- tags - tags
- /^[\d-]+-stable(-ee)?/ - /[\d-]+-stable(-ee)?/
- /^security-/ - /^security-/
- branches@gitlab-org/gitlab-ee - branches@gitlab-org/gitlab-ee
- branches@gitlab/gitlab-ee - branches@gitlab/gitlab-ee
@ -685,10 +682,13 @@ gitlab:assets:compile:
SKIP_STORAGE_VALIDATION: "true" SKIP_STORAGE_VALIDATION: "true"
WEBPACK_REPORT: "true" WEBPACK_REPORT: "true"
NO_COMPRESSION: "true" NO_COMPRESSION: "true"
# we override the max_old_space_size to prevent OOM errors
NODE_OPTIONS: --max_old_space_size=3584
script: script:
- date - date
- yarn install --frozen-lockfile --production --cache-folder .yarn-cache - yarn install --frozen-lockfile --production --cache-folder .yarn-cache
- date - date
- free -m
- bundle exec rake gitlab:assets:compile - bundle exec rake gitlab:assets:compile
artifacts: artifacts:
name: webpack-report name: webpack-report
@ -828,8 +828,6 @@ lint:javascript:report:
- setup-test-env - setup-test-env
before_script: [] before_script: []
script: script:
- date
- find app/ spec/ -name '*.js' -exec sed --in-place 's|/\* eslint-disable .*\*/||' {} \; # run report over all files
- date - date
- yarn run eslint-report || true # ignore exit code - yarn run eslint-report || true # ignore exit code
artifacts: artifacts:
@ -884,3 +882,15 @@ gitlab_git_test:
cache: {} cache: {}
script: script:
- spec/support/prepare-gitlab-git-test-for-commit --check-for-changes - spec/support/prepare-gitlab-git-test-for-commit --check-for-changes
no_ee_check:
<<: *dedicated-runner
<<: *except-docs-and-qa
variables:
SETUP_DB: "false"
before_script: []
cache: {}
script:
- scripts/no-ee-check
only:
- //@gitlab-org/gitlab-ce

View file

@ -1,9 +0,0 @@
### Description
(Include problem, use cases, benefits, and/or goals)
### Proposal
### Links / references
/label ~"feature proposal"

View file

@ -0,0 +1,15 @@
### Problem to solve
### Further details
(Include use cases, benefits, and/or goals)
### Proposal
### What does success look like, and how can we measure that?
(If no way to measure success, link to an issue that will implement a way to measure this)
### Links / references
/label ~"feature proposal"

View file

@ -39,6 +39,7 @@ Set the title to: `[Security] Description of the original issue`
- [ ] Add the nickname of the external user who found the issue (and/or HackerOne profile) to the Thanks row in the [details section](#details) - [ ] Add the nickname of the external user who found the issue (and/or HackerOne profile) to the Thanks row in the [details section](#details)
### Summary ### Summary
#### Links #### Links
| Description | Link | | Description | Link |

View file

@ -1,7 +1,7 @@
Add a description of your merge request here. Merge requests without an adequate Add a description of your merge request here. Merge requests without an adequate
description will not be reviewed until one is added. description will not be reviewed until one is added.
## Database Checklist ## Database checklist
When adding migrations: When adding migrations:
@ -31,18 +31,20 @@ When removing columns, tables, indexes or other structures:
- [ ] Removed these in a post-deployment migration - [ ] Removed these in a post-deployment migration
- [ ] Made sure the application no longer uses (or ignores) these structures - [ ] Made sure the application no longer uses (or ignores) these structures
## General Checklist ## General checklist
- [ ] [Changelog entry](https://docs.gitlab.com/ee/development/changelog.html) added, if necessary - [ ] [Changelog entry](https://docs.gitlab.com/ee/development/changelog.html) added, if necessary
- [ ] [Documentation created/updated](https://docs.gitlab.com/ee/development/doc_styleguide.html) - [ ] [Documentation created/updated](https://docs.gitlab.com/ee/development/doc_styleguide.html)
- [ ] API support added - [ ] API support added
- [ ] Tests added for this feature/bug - [ ] Tests added for this feature/bug
- Review - Conform by the [code review guidelines](https://docs.gitlab.com/ee/development/code_review.html)
- [ ] Has been reviewed by Backend - [ ] Has been reviewed by a Backend maintainer
- [ ] Has been reviewed by Database - [ ] Has been reviewed by a Database specialist
- [ ] Conform by the [merge request performance guides](https://docs.gitlab.com/ee/development/merge_request_performance_guidelines.html) - [ ] Conform by the [merge request performance guides](https://docs.gitlab.com/ee/development/merge_request_performance_guidelines.html)
- [ ] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/CONTRIBUTING.md#style-guides) - [ ] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/CONTRIBUTING.md#style-guides)
- [ ] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits) - [ ] If you have multiple commits, please combine them into a few logically organized commits by [squashing them](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
- [ ] Internationalization required/considered - [ ] Internationalization required/considered
- [ ] If paid feature, have we considered GitLab.com plan and how it works for groups and is there a design for promoting it to users who aren't on the correct plan - [ ] If paid feature, have we considered GitLab.com plan and how it works for groups and is there a design for promoting it to users who aren't on the correct plan
- [ ] End-to-end tests pass (`package-and-qa` manual pipeline job) - [ ] End-to-end tests pass (`package-and-qa` manual pipeline job)
/label ~database

2
.nvmrc
View file

@ -1 +1 @@
9.0.0 8.11.3

View file

@ -10,10 +10,6 @@
Capybara/CurrentPathExpectation: Capybara/CurrentPathExpectation:
Enabled: false Enabled: false
# Offense count: 956
Capybara/FeatureMethods:
Enabled: false
# Offense count: 23 # Offense count: 23
FactoryBot/DynamicAttributeDefinedStatically: FactoryBot/DynamicAttributeDefinedStatically:
Exclude: Exclude:
@ -173,7 +169,6 @@ Lint/UriEscapeUnescape:
- 'spec/requests/api/files_spec.rb' - 'spec/requests/api/files_spec.rb'
- 'spec/requests/api/internal_spec.rb' - 'spec/requests/api/internal_spec.rb'
- 'spec/requests/api/issues_spec.rb' - 'spec/requests/api/issues_spec.rb'
- 'spec/requests/api/v3/issues_spec.rb'
# Offense count: 1 # Offense count: 1
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
@ -333,8 +328,6 @@ RSpec/ScatteredSetup:
- 'spec/lib/gitlab/bitbucket_import/importer_spec.rb' - 'spec/lib/gitlab/bitbucket_import/importer_spec.rb'
- 'spec/lib/gitlab/git/env_spec.rb' - 'spec/lib/gitlab/git/env_spec.rb'
- 'spec/requests/api/jobs_spec.rb' - 'spec/requests/api/jobs_spec.rb'
- 'spec/requests/api/v3/builds_spec.rb'
- 'spec/requests/api/v3/projects_spec.rb'
- 'spec/services/projects/create_service_spec.rb' - 'spec/services/projects/create_service_spec.rb'
# Offense count: 1 # Offense count: 1
@ -490,7 +483,7 @@ Style/EmptyLiteral:
- 'lib/gitlab/fogbugz_import/importer.rb' - 'lib/gitlab/fogbugz_import/importer.rb'
- 'lib/gitlab/git/diff_collection.rb' - 'lib/gitlab/git/diff_collection.rb'
- 'lib/gitlab/gitaly_client.rb' - 'lib/gitlab/gitaly_client.rb'
- 'scripts/trigger-build-omnibus' - 'scripts/trigger-build'
- 'spec/features/merge_requests/versions_spec.rb' - 'spec/features/merge_requests/versions_spec.rb'
- 'spec/helpers/merge_requests_helper_spec.rb' - 'spec/helpers/merge_requests_helper_spec.rb'
- 'spec/lib/gitlab/request_context_spec.rb' - 'spec/lib/gitlab/request_context_spec.rb'
@ -618,7 +611,6 @@ Style/OrAssignment:
Exclude: Exclude:
- 'app/models/concerns/token_authenticatable.rb' - 'app/models/concerns/token_authenticatable.rb'
- 'lib/api/commit_statuses.rb' - 'lib/api/commit_statuses.rb'
- 'lib/api/v3/members.rb'
- 'lib/gitlab/project_transfer.rb' - 'lib/gitlab/project_transfer.rb'
# Offense count: 50 # Offense count: 50
@ -781,7 +773,6 @@ Style/TernaryParentheses:
- 'app/finders/projects_finder.rb' - 'app/finders/projects_finder.rb'
- 'app/helpers/namespaces_helper.rb' - 'app/helpers/namespaces_helper.rb'
- 'features/support/capybara.rb' - 'features/support/capybara.rb'
- 'lib/api/v3/projects.rb'
- 'lib/gitlab/ci/build/artifacts/metadata/entry.rb' - 'lib/gitlab/ci/build/artifacts/metadata/entry.rb'
- 'spec/requests/api/pipeline_schedules_spec.rb' - 'spec/requests/api/pipeline_schedules_spec.rb'
- 'spec/support/capybara.rb' - 'spec/support/capybara.rb'

View file

@ -1 +1 @@
2.3.7 2.4.4

View file

@ -46,8 +46,9 @@ linters:
# - properties # - properties
# - @include declarations with inner @content # - @include declarations with inner @content
# - nested rule sets. # - nested rule sets.
# Disabled to minimize Bootstrap migration footprint
DeclarationOrder: DeclarationOrder:
enabled: true enabled: false
# `scss-lint:disable` control comments should be preceded by a comment # `scss-lint:disable` control comments should be preceded by a comment
# explaining why these linters are being disabled for this file. # explaining why these linters are being disabled for this file.

View file

@ -2,26 +2,626 @@
documentation](doc/development/changelog.md) for instructions on adding your own documentation](doc/development/changelog.md) for instructions on adding your own
entry. entry.
## 10.8.7 (2018-07-26) ## 11.1.8 (2018-10-05)
### Security (3 changes)
- Filter user sensitive data from discussions JSON. !2539
- Properly filter private references from system notes.
- Markdown API no longer displays confidential title references unless authorized.
## 11.1.7 (2018-09-26)
### Security (6 changes)
- Redact confidential events in the API.
- Set timeout for syntax highlighting.
- Sanitize JSON data properly to fix XSS on Issue details page.
- Fix stored XSS in merge requests from imported repository.
- Fix xss vulnerability sourced from package.json.
- Block loopback addresses in UrlBlocker.
## 11.1.6 (2018-08-28)
- No changes.
## 11.1.5 (2018-08-27)
### Security (3 changes)
- Fixed persistent XSS rendering/escaping of diff location lines.
- Adding CSRF protection to Hooks resend action.
- Block link-local addresses in URLBlocker.
### Fixed (1 change, 1 of them is from the community)
- Sanitize git URL in import errors. (Jamie Schembri)
## 11.1.4 (2018-07-30)
- No changes.
## 11.1.3 (2018-07-27)
### Fixed (8 changes, 1 of them is from the community)
- Rework some projects table indexes around repository_storage field. !20377
- Fix navigation to First and Next discussion on MR Changes tab. !20434
- Fix showing outdated discussions on Changes tab. !20445
- Fix autosave and ESC confirmation issues for MR discussions. !20569
- Fix rendering of the context lines in MR diffs page. !20642
- Don't overflow project/group dropdown results. !20704 (gfyoung)
- Fixed IDE not opening JSON files. !20798
- Disable Gitaly timeouts when creating or restoring backups. !20810
### Performance (1 change)
- Reduces the client side memory footprint on merge requests. !20744
## 11.1.2 (2018-07-26)
### Security (4 changes) ### Security (4 changes)
- Don't expose project names in various counters.
- Don't expose project names in GitHub counters.
- Adding CSRF protection to Hooks test action. - Adding CSRF protection to Hooks test action.
- Don't expose project names in GitHub counters.
- Don't expose project names in various counters.
- Fixed XSS in branch name in Web IDE. - Fixed XSS in branch name in Web IDE.
### Fixed (1 change) ### Fixed (1 change)
- Escapes milestone and label's names on flash notice when promoting them. - Escapes milestone and label's names on flash notice when promoting them.
### Performance (1 change)
## 10.8.6 (2018-07-17) - Fix slow Markdown rendering. !20820
### Security (2 changes)
## 11.1.1 (2018-07-23)
### Fixed (2 changes)
- Add missing Gitaly branch_update nil checks. !20711
- Fix filename for accelerated uploads.
### Added (1 change)
- Add uploader support to Import/Export uploads. !20484
## 11.1.0 (2018-07-22)
### Security (6 changes)
- Fix XSS vulnerability for table of content generation.
- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
- HTML escape branch name in project graphs page.
- HTML escape the name of the user in ProjectsHelper#link_to_member.
- Don't show events from internal projects for anonymous users in public feed.
- Fix symlink vulnerability in project import. - Fix symlink vulnerability in project import.
- Merge branch 'fix-mr-widget-border' into 'master'.
### Removed (1 change)
- Remove deprecated object_storage_upload queue.
### Fixed (98 changes, 52 of them are from the community)
- Keep lists ordered when copying only list items. !18522 (Jan Beckmann)
- Fix bug where maintainer would not be allowed to push to forks with merge requests that have `Allow maintainer edits` enabled. !18968
- mergeError message has been binded using v-html directive. !19058 (Murat Dogan)
- Set MR target branch to default branch if target branch is not valid. !19067
- Fix CSS for buttons not to be hidden on issues/MR title. !19176 (Takuya Noguchi)
- Use same gem versions for rails5 as for rails4 where possible. !19498 (Jasper Maes)
- Fix extra blank line at start of rendered reStructuredText code block. !19596
- Fix username validation order on signup, resolves #45575. !19610 (Jan Beckmann)
- Make quick commands case insensitive. !19614 (Jan Beckmann)
- Remove incorrect CI doc re: PowerShell. !19622 (gfyoung)
- Fixes Microsoft Teams notifications for pipeline events. !19632 (Jeff Brown)
- Fix branch name encoding for dropdown on issue page. !19634
- Rails5 fix expected `issuable.reload.updated_at` to have changed. !19733 (Jasper Maes)
- Rails5 fix stack level too deep. !19762 (Jasper Maes)
- Rails5 ActionController::ParameterMissing: param is missing or the value is empty: application_setting. !19763 (Jasper Maes)
- Invalidate cache with project details when repository is updated. !19774
- Rails5 fix no implicit conversion of Hash into String. ActionController::Parameters no longer returns an hash in Rails 5. !19792 (Jasper Maes)
- [Rails5] Fix snippets_finder arel queries. !19796 (@blackst0ne)
- Fix fields for author & assignee in MR API docs. !19798 (gfyoung)
- Remove scrollbar in Safari in repo settings page. !19809 (gfyoung)
- Omits operartions and kubernetes item from project sidebar when repository or builds are disabled. !19835
- Rails5 fix passing Group objects array into for_projects_and_groups milestone scope. !19863 (Jasper Maes)
- Fix chat service tag notifications not sending when only default branch enabled. !19864
- Only show new issue / new merge request on group page when issues / merge requests are enabled. !19869 (Jan Beckmann)
- [Rails5] Explicitly set request.format for blob_controller. !19876 (@blackst0ne)
- [Rails5] Fix optimistic lock value. !19878 (@blackst0ne)
- Rails5 fix update_attribute usage not causing a save. !19881 (Jasper Maes)
- Rails5 fix connection execute return integer instead of string. !19901 (Jasper Maes)
- Rails5 fix format in uploads actions. !19907 (Jasper Maes)
- [Rails5] Fix "-1 is not a valid data_store". !19917 (@blackst0ne)
- [Rails5] Invalid single-table inheritance type: Group is not a subclass of Namespace. !19918 (@blackst0ne)
- [Rails5] Fix pipeline_schedules_controller_spec. !19919 (@blackst0ne)
- Rails5 fix passing Group objects array into for_projects_and_groups milestone scope. !19920 (Jasper Maes)
- Rails5 update Gemfile.rails5.lock. !19921 (Jasper Maes)
- [Rails5] Fix sessions_controller_spec. !19936 (@blackst0ne)
- [Rails5] Set request.format for artifacts_controller. !19937 (@blackst0ne)
- Fix webhook error when password is not present. !19945 (Jan Beckmann)
- Fix label and milestone duplicated records and IID errors. !19961
- Rails5 fix expected: 1 time with arguments: (97, anything, {"squash"=>false}) received: 0 times. !20004 (Jasper Maes)
- Rails5 fix Projects::PagesController spec. !20007 (Jasper Maes)
- [Rails5] Fix ActionCable '/cable' mountpoint conflict. !20015 (@blackst0ne)
- Fix branches are not shown in Merge Request dropdown when preferred language is not English. !20016 (Hiroyuki Sato)
- Rails5 fix Admin::HooksController. !20017 (Jasper Maes)
- Rails5 fix expected: 0 times with any arguments received: 1 time with arguments: DashboardController. !20018 (Jasper Maes)
- [Rails5] Set request.format in commits_controller. !20023 (@blackst0ne)
- Keeps the label on an issue when the issue is moved. !20036
- Cleanup Prometheus ruby metrics. !20039 (Ben Kochie)
- Rails 5 fix Capybara::ElementNotFound: Unable to find visible css #modal-revert-commit and expected: "/bar" got: "/foo". !20044 (Jasper Maes)
- [Rails5] Force the callback run first. !20055 (@blackst0ne)
- Add readme button to non-empty project page. !20104
- Fixed bug when editing a comment in an issue,the preview mode is toggled in the main textarea. !20112 (Constance Okoghenun)
- Ignore unknown OAuth sources in ApplicationSetting. !20129
- Fix paragraph line height for emoji. !20137 (George Tsiolis)
- Fixes issue with uploading same image to Profile Avatar twice. !20161 (Chirag Bhatia)
- Rails5 fix arel from in mysql_median_datetime_sql. !20167 (Jasper Maes)
- Adds the `locked` state to the merge request API so that it can be used as a search filter. !20186
- Enable Doorkeeper option to avoid generating new tokens when users login via oauth. !20200
- Fix OAuth Application Authorization screen to appear with each access. !20216
- Rails5 fix MySQL milliseconds problem in specs. !20221 (Jasper Maes)
- Rails5 fix Mysql comparison failure caused by milliseconds problem. !20222 (Jasper Maes)
- Updated last commit link color. !20234 (Constance Okoghenun)
- Fixed Merge request changes dropdown displays incorrectly. !20237 (Constance Okoghenun)
- Show jobs from same pipeline in sidebar in job details view. !20243
- [Rails5] Fix milestone GROUP BY query. !20256 (@blackst0ne)
- Line separator to the left of the 'Admin area' wrench icon had vanished. !20282 (bitsapien)
- Check if archived trace exist before archive it. !20297
- Load Devise with Omniauth when auto_sign_in_with_provider is configured. !20302
- Fix link to job when creating a new issue from a failed job. !20328
- Fix double "in" in time to artifact deletion message. !20357 (@bbodenmiller)
- Fix wrong role badge displayed in projects dashboard. !20374
- Stop relying on migrations in the CacheableAttributes cache key and cache attributes for 1 minute instead. !20389
- Fixes toggle discussion button not expanding collapsed discussions. !20452
- Resolve compatibility issues with node 6. !20461
- Fixes base command used in Helm installations. !20471
- Fix RSS button interaction on Dashboard, Project and Group activities. !20549
- Use appropriate timeout on Gitaly server info checks, avoid error on timeout. !20552
- Remove healthchecks from prometheus endpoint. !20565
- Render MR page when diffs cannot be fetched from the database or the git repository. !20680
- Expire correct method caches after HEAD changed.
- Ensure MR diffs always exist in the PR importer.
- Fix overlapping file title and file actions in MR changes tag.
- Mark MR as merged regardless of errors when closing issues.
- Fix performance bar modal visibility in Safari.
- Prevent browser autocomplete for milestone date fields.
- Limit the action suffixes in transaction metrics.
- Add /uploads subdirectory to allowed upload paths.
- Fix cross-project label references.
- Invalidate merge request diffs cache if diff data change.
- Don't show context button for diffs of deleted files.
- Structure getters for diff Store properly and adds specs.
- Bump rugged to 0.27.2.
- Fix Bamboo CI status not showing for branch plans.
- Fixed bug that allowed to remove other wiki pages if the title had wildcard characters.
- Disabled Web IDE autocomplete suggestions for Markdown files. (Isaac Smith)
- Fix merge request diffs when created with gitaly_diff_between enabled.
- Properly detect label reference if followed by period or question mark.
- Deactivate new KubernetesService created from active template to prevent project creation from failing.
- Allow trailing whitespace on blockquote fence lines.
### Deprecated (1 change)
- Removes unused bootstrap 4 scss files. !19423
### Changed (33 changes, 16 of them are from the community)
- Change label link vertical alignment property. !18777 (George Tsiolis)
- Updated the icon for expand buttons to ellipsis. !18793 (Constance Okoghenun)
- Create new or add existing Kubernetes cluster from a single page. !18963
- Use object storage as the first class persistable store for new live trace architecture. !19515
- Hide project name if searching against a project. !19595
- Allows you to create another deploy token dimmediately after creating one. !19639
- Removes the environment scope field for users that cannot edit it. !19643
- Don't hash user ID in OIDC subject claim. !19784 (Markus Koller)
- Milestone page list redesign. !19832 (Constance Okoghenun)
- Add environment dropdown for the metrics page. !19833
- Allow querying a single merge request within a project. !19853
- Update WebIDE to show file in tree on load. !19887
- Remove small container width. !19893 (George Tsiolis)
- Improve U2F workflow when using unsupported browsers. !19938 (Jan Beckmann)
- Update Web IDE file tree styles. !19969
- Highlight cluster settings message. !19996 (George Tsiolis)
- Fade uneditable area in Web IDE. !20008
- Update pipeline icon in web ide sidebar. !20058 (George Tsiolis)
- Revert merge request discussion buttons padding. !20060 (George Tsiolis)
- Fix boards issue highlight. !20063 (George Tsiolis)
- Update external link icon in header user dropdown. !20150 (George Tsiolis)
- Update external link icon in merge request widget. !20154 (George Tsiolis)
- Update environments nav controls icons. !20199 (George Tsiolis)
- Update integrations external link icons. !20205 (George Tsiolis)
- Fixes an issue where migrations instead of schema loading were run. !20227
- Add title placeholder for new issues. !20271 (George Tsiolis)
- Close revoke deploy token modal on escape keypress. !20347 (George Tsiolis)
- Change environment scope text depending on number of project clusters. Update form to only include form-groups.
- Improve Web IDE commit flow.
- Add machine type and pricing documentation links, add class to labels to make bold.
- Remove remaining traces of the Allocations Gem.
- Use one column form layout on Admin Area Settings page.
- Add back copy for existing gcp accounts within offer banner.
### Performance (16 changes, 4 of them are from the community)
- Fully migrate pipeline stages position. !19369
- Use Tooltip component in MrWidgetAuthorTime vue comonent. !19635 (George Tsiolis)
- Move boards modal EmptyState vue component. !20068 (George Tsiolis)
- Bump carrierwave gem verion to 1.2.3. !20287
- Remove redundant query when removing trace. !20324
- Improves performance of mr code, by fixing the state being mutated outside of the store in the util function trimFirstCharOfLineContent and in map operations. Avoids map operation in an empty array. Adds specs to the trimFirstCharOfLineContent function. !20380 (filipa)
- Reduce the number of queries when searching for groups. !20398
- Improve render performance of large wiki pages. !20465 (Peter Leitzen)
- Improves performance on Merge Request diff tab by removing the scroll event listeners being added to every file.
- Remove the ci_job_request_with_tags_matcher.
- Updated Gitaly fail-fast timeout values.
- Add index on deployable_type/id for deployments.
- Eliminate N+1 queries in LFS file locks checks during a push.
- Fix performance problem of accessing tag list for projects api endpoints.
- Improve performance of listing users without projects.
- Fixed pagination of web hook logs.
### Added (29 changes, 9 of them are from the community)
- Add dropdown to Groups link in top bar. !18280
- Web IDE supports now Image + Download Diff Viewing. !18768
- Use CommonMark syntax and rendering for new Markdown content. !19331
- Add SHA256 and HEAD on File API. !19439 (ahmet2mir)
- Add filename filtering to code search. !19509
- Add CI_PIPELINE_URL and CI_JOB_URL. !19618
- Expose visibility via Snippets API. !19620 (Jan Beckmann)
- Fixed pagination of groups API. !19665 (Marko, Peter)
- Added id sorting option to GET groups and subgroups API. !19665 (Marko, Peter)
- Add a link to the contributing page in the user dropdown. !19708
- Add Object Storage to project export. !20105
- Change avatar image in the header when user updates their avatar. !20119 (Jamie Schembri)
- Allow straight diff in Compare API. !20120 (Maciej Nowak)
- Add transfer project API endpoint. !20122 (Aram Visser)
- Expose permissions of the current user on resources in GraphQL. !20152
- Run repository checks in parallel for each shard. !20179
- Add pipeline lists to GraphQL. !20249
- Add option to add README when creating a project. !20335
- Add option to hide third party offers in admin application settings. !20379
- Add /confidential quick action. (Jan Beckmann)
- Support direct_upload for generic uploads.
- Display merge request title & description in Web IDE.
- Prune web hook logs older than 90 days.
- Add Web Terminal for Ci Builds. (Vicky Chijwani)
- Expose whether current user can push into a branch on branches API.
- Present state indication on GFM preview.
- migrate backup rake task to gitaly.
- Add Gitlab::SQL:CTE for easily building CTE statements.
- Added with_statsoption for GET /projects/:id/repository/commits.
### Other (28 changes, 11 of them are from the community)
- Move some Gitaly RPC's to opt-out. !19591
- Bump grape-path-helpers to 1.0.5. !19604 (@blackst0ne)
- Add CI job to check Gemfile.rails5.lock. !19605 (@blackst0ne)
- Move Gitaly branch/tag/ref RPC's to opt-out. !19644
- CE port gitlab-ee!6112. !19714
- Enable no-multi-assignment in JS files. !19808 (gfyoung)
- Enable no-restricted globals in JS files. !19877 (gfyoung)
- Improve no-multi-assignment fixes after enabling rule. !19915 (gfyoung)
- Enable prefer-structuring in JS files. !19943 (gfyoung)
- Enable frozen string in app/workers/*.rb. !19944 (gfyoung)
- Uses long sha version of the merged commit in MR widget copy to clipboard button. !19955
- Update new group page to better explain what groups are. !19991
- Update new SSH key page to improve copy. !19994
- Update new SSH key page to improve key input validation. !19997
- Gitaly metrics check for read/writeability. !20022
- Add ellispsis to web ide commit button. !20030
- Minor style changes to personal access token form and scope checkboxes. !20052
- Finish enabling frozen string for app/workers/*.rb. !20197 (gfyoung)
- Allows settings sections to expand by default when linking to them. !20211
- Enable frozen string in apps/validators/*.rb. !20220 (gfyoung)
- update bcrypt to also support libxcrypt. !20260 (muhammadn)
- Enable frozen string in apps/validators/*.rb. !20382 (gfyoung)
- Removes unused vuex code in mr refactor and removes unneeded dependencies. !20499
- Delete non-latest merge request diff files upon merge.
- Schedule workers to delete non-latest diffs in post-migration.
- Remove the use of `is_shared` of `Ci::Runner`.
- Add more detailed logging to githost.log when rebasing.
- Use monospaced font for MR diff commit link ref on GFM.
## 11.0.3 (2018-07-05)
### Fixed (14 changes, 1 of them is from the community)
- Revert merge request widget button max height. !20175 (George Tsiolis)
- Implement upload copy when moving an issue with upload on object storage. !20191
- Fix broken '!' support to autocomplete MRs in GFM fields. !20204
- Restore showing Elasticsearch and Geo status on dashboard. !20276
- Fix merge request page rendering error when its target/source branch is missing. !20280
- Fix sidebar collapse breapoints for job and wiki pages.
- fix size of code blocks in headings.
- Fix loading screen for search autocomplete dropdown.
- Fix ambiguous due_date column for Issue scopes.
- Always serve favicon from main GitLab domain so that CI badge can be drawn over it.
- Fix tooltip flickering bug.
- Fix refreshing cache keys for open issues count.
- Replace deprecated bs.affix in merge request tabs with sticky polyfill.
- Prevent pipeline job tooltip from scrolling off dropdown container.
## 11.0.2 (2018-06-26)
### Fixed (8 changes, 1 of them is from the community)
- Serve favicon image always from the main GitLab domain to avoid issues with CORS. !19810 (Alexis Reigel)
- Specify chart version when installing applications on Clusters. !20010
- Fix invalid fuzzy translations being generated during installation. !20048
- Fix incremental rollouts for Auto DevOps. !20061
- Notify conflict for only open merge request. !20125
- Only load Omniauth if enabled. !20132
- Fix sorting by name on explore projects page. !20162
- Fix alert button styling so that they don't show up white.
### Performance (1 change)
- Remove performance bottleneck preventing large wiki pages from displaying. !20174
### Added (1 change)
- Add support for verifying remote uploads, artifacts, and LFS objects in check rake tasks. !19501
## 11.0.1 (2018-06-21)
### Security (5 changes)
- Fix XSS vulnerability for table of content generation.
- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
- HTML escape branch name in project graphs page.
- HTML escape the name of the user in ProjectsHelper#link_to_member.
- Don't show events from internal projects for anonymous users in public feed.
## 11.0.0 (2018-06-22)
### Security (3 changes)
- Fix API to remove deploy key from project instead of deleting it entirely.
- Fixed bug that allowed importing arbitrary project attributes.
- Prevent user passwords from being changed without providing the previous password.
### Removed (2 changes)
- Removed API v3 from the codebase. !18970
- Removes outdated `g t` shortcut for TODO in favor of `Shift+T`. !19002
### Fixed (69 changes, 23 of them are from the community)
- Optimize the upload migration proces. !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)
- Fix double-brackets being linkified in wiki markdown. !18524 (brewingcode)
- Use case in-sensitive ordering by name for dashboard. !18553 (@vedharish)
- Fix width of contributors graphs. !18639 (Paul Vorbach)
- Fix modal width of shorcuts help page. !18766 (Lars Greiss)
- Add missing tooltip to creation date on container registry overview. !18767 (Lars Greiss)
- Add missing migration for minimal Project build_timeout. !18775
- Update commit status from external CI services less aggressively. !18802
- Fix Runner contacted at tooltip cache. !18810
- Added support for LFS Download in the importing process. !18871
- Fix issue board bug with long strings in titles. !18924
- Does not log failed sign-in attempts when the database is in read-only mode. !18957
- Fixes 500 error on /estimate BIG_VALUE. !18964 (Jacopo Beschi @jacopo-beschi)
- Forbid to patch traces for finished jobs. !18969
- Do not allow to trigger manual actions that were skipped. !18985
- Renamed 'Overview' to 'Project' in collapsed contextual navigation at a project level. !18996 (Constance Okoghenun)
- Fixed bug where generated api urls didn't add the base url if set. !19003
- Fixed badge api endpoint route when relative url is set. !19004
- Fixes: Runners search input placeholder is cut off. !19015 (Jacopo Beschi @jacopo-beschi)
- Exclude CI_PIPELINE_ID from variables supported in dynamic environment name. !19032
- Updates updated_at on label changes. !19065 (Jacopo Beschi @jacopo-beschi)
- Disallow updating job status if the job is not running. !19101
- Fix FreeBSD can not upload artifacts due to wrong tmp path. !19148
- Check for nil AutoDevOps when saving project CI/CD settings. !19190
- Missing timeout value in object storage pre-authorization. !19201
- Use strings as properties key in kubernetes service spec. !19265 (Jasper Maes)
- Fixed HTTP_PROXY environment not honored when reading remote traces. !19282 (NLR)
- Updates ReactiveCaching clear_reactive_caching method to clear both data and alive caching. !19311
- Fixes the styling on the modal headers. !19312 (samdbeckham)
- Fixes a spelling error on the new label page. !19316 (samdbeckham)
- Rails5 fix arel from. !19340 (Jasper Maes)
- Support rails5 in postgres indexes function and fix some migrations. !19400 (Jasper Maes)
- Fix repository archive generation when hashed storage is enabled. !19441
- Rails 5 fix unknown keywords: changes, key_id, project, gl_repository, action, secret_token, protocol. !19466 (Jasper Maes)
- Rails 5 fix glob spec. !19469 (Jasper Maes)
- Showing project import_status in a humanized form no longer gives an error. !19470
- Make avatars/icons hidden on mobile. !19585 (Takuya Noguchi)
- Fix active tab highlight when creating new merge request. !19781 (Jan Beckmann)
- Fixes Web IDE button on merge requests when GitLab is installed with relative URL.
- Unverified hover state color changed to black.
- Fix &nbsp; after sign-in with Google button.
- Don't trim incoming emails that create new issues. (Cameron Crockett)
- Wrapping problem on the issues page has been fixed.
- Fix resolvable check if note's commit could not be found.
- Fix filename matching when processing file or blob search results.
- Allow maintainers to retry pipelines on forked projects (if allowed in merge request).
- Fix deletion of Object Store uploads.
- Fix overflowing Failed Jobs table in sm viewports on IE11.
- Adjust insufficient diff hunks being persisted on NoteDiffFile.
- Render calendar feed inline when accessed from GitLab.
- Line height fixed. (Murat Dogan)
- Use upload ID for creating lease key for file uploaders.
- Use Github repo visibility during import while respecting restricted visibility levels.
- Adjust permitted params filtering on merge scheduling.
- Fix unscrollable Markdown preview of WebIDE on Firefox.
- Enforce UTF-8 encoding on user input in LogrageWithTimestamp formatter and filter out file content from logs.
- Fix project destruction failing due to idle in transaction timeouts.
- Add a unique and not null constraint on the project_features.project_id column.
- Expire Wiki content cache after importing a repository.
- Fix admin counters not working when PostgreSQL has secondaries.
- Fix backup creation and restore for specific Rake tasks.
- Fix cross-origin errors when attempting to download JavaScript attachments.
- Fix api_json.log not always reporting the right HTTP status code.
- Fix attr_encryption key settings.
- Remove gray button styles.
- Fix print styles for markdown pages.
### Deprecated (4 changes)
- Deprecate Gemnasium project service. !18954
- Rephrasing Merge Request's 'allow edits from maintainer' functionality. !19061
- Rename issue scope created-by-me to created_by_me, and assigned-to-me to assigned_to_me. !44799
- Migrate any remaining jobs from deprecated `object_storage_upload` queue.
### Changed (42 changes, 11 of them are from the community)
- Add support for smarter system notes. !17164
- Automatically accepts project/group invite by email after user signup. !17634 (Jacopo Beschi @jacopo-beschi)
- Dynamically fetch GCP cluster creation parameters. !17806
- Label list page redesign. !18466
- Move discussion actions to the right for small viewports. !18476 (George Tsiolis)
- Add 2FA filter to the group members page. !18483
- made listing and showing public issue apis available without authentication. !18638 (haseebeqx)
- Refactoring UrlValidators to include url blocking. !18686
- Removed "(Beta)" from "Auto DevOps" messages. !18759
- Expose runner ip address to runners API. !18799 (Lars Greiss)
- Moves MR widget external link icon to the right. !18828 (Jacopo Beschi @jacopo-beschi)
- Add support for 'active' setting on Runner Registration API endpoint. !18848
- Add dot to separate system notes content. !18864
- Remove modalbox confirmation when retrying a pipeline. !18879
- Remove docker pull prefix from registry clipboard feature. !18933 (Lars Greiss)
- Move project sidebar sub-entries 'Environments' and 'Kubernetes' from 'CI/CD' to a new entry 'Operations'. !18941
- Updated icons for branch and tag names in commit details. !18953 (Constance Okoghenun)
- Expose readme url in Project API. !18960 (Imre Farkas)
- Changes keyboard shortcut of Activity feed to `g v`. !19002
- Updated Mattermost integration to use API v4 and only allow creation of Mattermost slash commands in the current user's teams. !19043 (Harrison Healey)
- Add shortcuts to Web IDE docs and modal. !19044
- Rename merge request widget author component. !19079 (George Tsiolis)
- Rename the Master role to Maintainer. !19080
- Use "right now" for short time periods. !19095
- Update 404 and 403 pages with helpful actions. !19096
- Add username to terms message in git and API calls. !19126
- Change the IDE file buttons for an "Open in file view" button. !19129 (Sam Beckham)
- Removes redundant script failure message from Job page. !19138
- Add flash notice if user has already accepted terms and allow users to continue to root path. !19156
- Redesign group settings page into expandable sections. !19184
- Hashed Storage: migration rake task now can be executed to specific project. !19268
- Make CI job update entrypoint to work as keep-alive endpoint. !19543
- Avoid checking the user format in every url validation. !19575
- Apply notification settings level of groups to all child objects.
- Support restoring repositories into gitaly.
- Bump omniauth-gitlab to 1.0.3.
- Move API group deletion to Sidekiq.
- Improve Failed Jobs tab in the Pipeline detail page.
- Add additional theme color options.
- Include milestones from parent groups when assigning a milestone to an issue or merge request.
- Restore API v3 user endpoint.
- Hide merge request option in IDE when disabled.
### Performance (28 changes, 1 of them is from the community)
- Add backgound migration for filling nullfied file_store columns. !18557
- 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
- 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
- Use NPM provided version of SortableJS. !19274
- Improve performance of group issues filtering on GitLab.com. !19429
- Improve performance of LFS integrity check. !19494
- Fix an N+1 when loading user avatars.
- Only preload member records for the relevant projects/groups/user in projects API.
- Fix some sources of excessive query counts when calculating notification recipients.
- Optimise PagesWorker usage.
- Optimise paused runners to reduce amount of used requests.
- Update runner cached informations without performing validations.
- Improve performance of project pipelines pages.
- Persist truncated note diffs on a new table.
- Remove unused running_or_pending_build_count.
- Remove N+1 query for author in issues API.
- Eliminate N+1 queries with authors and push_data_payload in Events API.
- Eliminate cached N+1 queries for projects in Issue API.
- Eliminate N+1 queries for CI job artifacts in /api/prjoects/:id/pipelines/:pipeline_id/jobs.
- Fix N+1 with source_projects in merge requests API.
- Replace grape-route-helpers with our own grape-path-helpers.
- Move PR IO operations out of a transaction.
- Improve performance of GroupsController#show.
### Added (25 changes, 10 of them are from the community)
- Closes MR check out branch modal with escape. (19050)
- Allow changing the default favicon to a custom icon. !14497 (Alexis Reigel)
- Export assigned issues in iCalendar feed. !17783 (Imre Farkas)
- When MR becomes unmergeable, notify and create todo for author and merge user. !18042
- Display help text below auto devops domain with nip.io domain name (#45561). !18496
- Add per-project pipeline id. !18558
- New design for wiki page deletion confirmation. !18712 (Constance Okoghenun)
- Updates updated_at on issuable when setting time spent. !18757 (Jacopo Beschi @jacopo-beschi)
- Expose artifacts_expire_at field for job entity in api. !18872 (Semyon Pupkov)
- Add support for variables expression pattern matching syntax. !18902
- Add API endpoint to render markdown text. !18926 (@blackst0ne)
- Add `Squash and merge` to GitLab Core (CE). !18956 (@blackst0ne)
- Adds keyboard shortcut `g k` for Kubernetes on Project pages. !19002
- Adds keyboard shortcut `g e` for Environments on Project pages. !19002
- Setup graphql with initial project & merge request query. !19008
- Adds JupyterHub to cluster applications. !19019
- Added ability to search by wiki titles. !19112
- Add Avatar API. !19121 (Imre Farkas)
- Add variables to POST api/v4/projects/:id/pipeline. !19124 (Jacopo Beschi @jacopo-beschi)
- Add deploy strategies to the Auto DevOps settings. !19172
- Automatize Deploy Token creation for Auto Devops. !19507
- Add anchor for incoming email regex.
- Support direct_upload with S3 Multipart uploads.
- Add Open in Xcode link for xcode repositories.
- Add pipeline status to the status bar of the Web IDE.
### Other (40 changes, 17 of them are from the community)
- Expand documentation for Runners API. !16484
- Order UsersController#projects.json by updated_at. !18227 (Takuya Noguchi)
- Replace the `project/issues/references.feature` spinach test with an rspec analog. !18769 (@blackst0ne)
- Replace the `project/merge_requests/references.feature` spinach test with an rspec analog. !18794 (@blackst0ne)
- Replace the `project/deploy_keys.feature` spinach test with an rspec analog. !18796 (@blackst0ne)
- Replace the `project/ff_merge_requests.feature` spinach test with an rspec analog. !18800 (@blackst0ne)
- Apply NestingDepth (level 5) (pages/pipelines.scss). !18830 (Takuya Noguchi)
- Replace the `project/forked_merge_requests.feature` spinach test with an rspec analog. !18867 (@blackst0ne)
- Remove Spinach. !18869 (@blackst0ne)
- Add NOT NULL constraints to project_authorizations. !18980
- Add helpful messages to empty wiki view. !19007
- Increase text limit for GPG keys (mysql only). !19069
- Take two for MR metrics population background migration. !19097
- Remove Gemnasium badge from project README.md. !19136 (Takuya Noguchi)
- Update awesome_print to 1.8.0. !19163 (Takuya Noguchi)
- Update email_spec to 2.2.0. !19164 (Takuya Noguchi)
- Update redis-namespace to 1.6.0. !19166 (Takuya Noguchi)
- Update rdoc to 6.0.4. !19167 (Takuya Noguchi)
- Updates the version of kubeclient from 3.0 to 3.1.0. !19199
- Fix UI broken in line profiling modal due to Bootstrap 4. !19253 (Takuya Noguchi)
- Add migration to disable the usage of DSA keys. !19299
- Use the default strings of timeago.js for timeago. !19350 (Takuya Noguchi)
- Update selenium-webdriver to 3.12.0. !19351 (Takuya Noguchi)
- Include username in output when testing SSH to GitLab. !19358
- Update screenshot in Gitlab.com integration documentation. !19433 (Tuğçe Nur Taş)
- Users can accept terms during registration. !19583
- Fix issue count on sidebar.
- Add merge requests list endpoint for groups.
- Upgrade GitLab from Bootstrap 3 to 4.
- Make ActiveRecordSubscriber rails 5 compatible.
- Show a more helpful error for import status.
- Log response body to production_json.log when a controller responds with a 422 status.
- Log Workhorse queue duration for Grape API calls.
- 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.
- 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.
## 10.8.5 (2018-06-21) ## 10.8.5 (2018-06-21)
@ -253,6 +853,38 @@ entry.
- Gitaly handles repository forks by default. - Gitaly handles repository forks by default.
## 10.7.6 (2018-06-21)
### Security (6 changes)
- Fix XSS vulnerability for table of content generation.
- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
- HTML escape branch name in project graphs page.
- HTML escape the name of the user in ProjectsHelper#link_to_member.
- Don't show events from internal projects for anonymous users in public feed.
- XSS fix to use safe_params instead of params in url_for helpers.
### Other (1 change)
- Replacing gollum libraries for gitlab custom libs. !18343
## 10.7.5 (2018-05-28)
### Security (3 changes)
- Prevent user passwords from being changed without providing the previous password.
- Fix API to remove deploy key from project instead of deleting it entirely.
- Fixed bug that allowed importing arbitrary project attributes.
## 10.7.4 (2018-05-21)
### Fixed (1 change)
- Fix error when deleting an empty list of refs.
## 10.7.3 (2018-05-02) ## 10.7.3 (2018-05-02)
### Fixed (8 changes) ### Fixed (8 changes)
@ -510,6 +1142,16 @@ entry.
- Upgrade Gitaly to upgrade its charlock_holmes. - Upgrade Gitaly to upgrade its charlock_holmes.
## 10.6.6 (2018-05-28)
### Security (4 changes)
- Do not allow non-members to create MRs via forked projects when MRs are private.
- Prevent user passwords from being changed without providing the previous password.
- Fix API to remove deploy key from project instead of deleting it entirely.
- Fixed bug that allowed importing arbitrary project attributes.
## 10.6.5 (2018-04-24) ## 10.6.5 (2018-04-24)
### Security (1 change) ### Security (1 change)

View file

@ -27,14 +27,15 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._
- [Helping others](#helping-others) - [Helping others](#helping-others)
- [I want to contribute!](#i-want-to-contribute) - [I want to contribute!](#i-want-to-contribute)
- [Workflow labels](#workflow-labels) - [Workflow labels](#workflow-labels)
- [Type labels (~"feature proposal", ~bug, ~customer, etc.)](#type-labels-feature-proposal-bug-customer-etc) - [Type labels](#type-labels)
- [Subject labels (~wiki, ~"container registry", ~ldap, ~api, etc.)](#subject-labels-wiki-container-registry-ldap-api-etc) - [Subject labels](#subject-labels)
- [Team labels (~"CI/CD", ~Discussion, ~Quality, ~Platform, etc.)](#team-labels-cicd-discussion-quality-platform-etc) - [Team labels](#team-labels)
- [Milestone labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#milestone-labels-deliverable-stretch-next-patch-release) - [Release Scoping labels](#release-scoping-labels)
- [Priority labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#bug-priority-labels-p1-p2-p3-etc) - [Bug Priority labels](#bug-priority-labels)
- [Severity labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#bug-severity-labels-s1-s2-s3-etc) - [Bug Severity labels](#bug-severity-labels)
- [Label for community contributors (~"Accepting Merge Requests")](#label-for-community-contributors-accepting-merge-requests) - [Severity impact guidance](#severity-impact-guidance)
- [Implement design & UI elements](#implement-design--ui-elements) - [Label for community contributors](#label-for-community-contributors)
- [Implement design & UI elements](#implement-design-ui-elements)
- [Issue tracker](#issue-tracker) - [Issue tracker](#issue-tracker)
- [Issue triaging](#issue-triaging) - [Issue triaging](#issue-triaging)
- [Feature proposals](#feature-proposals) - [Feature proposals](#feature-proposals)
@ -132,7 +133,7 @@ Most issues will have labels for at least one of the following:
- Type: ~"feature proposal", ~bug, ~customer, etc. - Type: ~"feature proposal", ~bug, ~customer, etc.
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc. - Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
- Team: ~"CI/CD", ~Discussion, ~Quality, ~Platform, etc. - Team: ~"CI/CD", ~Discussion, ~Quality, ~Platform, etc.
- Milestone: ~Deliverable, ~Stretch, ~"Next Patch Release" - Release Scoping: ~Deliverable, ~Stretch, ~"Next Patch Release"
- Priority: ~P1, ~P2, ~P3, ~P4 - Priority: ~P1, ~P2, ~P3, ~P4
- Severity: ~S1, ~S2, ~S3, ~S4 - Severity: ~S1, ~S2, ~S3, ~S4
@ -145,7 +146,7 @@ labels, you can _always_ add the team and type, and often also the subject.
[milestones-page]: https://gitlab.com/gitlab-org/gitlab-ce/milestones [milestones-page]: https://gitlab.com/gitlab-org/gitlab-ce/milestones
[labels-page]: https://gitlab.com/gitlab-org/gitlab-ce/labels [labels-page]: https://gitlab.com/gitlab-org/gitlab-ce/labels
### Type labels (~"feature proposal", ~bug, ~customer, etc.) ### Type labels
Type labels are very important. They define what kind of issue this is. Every Type labels are very important. They define what kind of issue this is. Every
issue should have one or more. issue should have one or more.
@ -161,28 +162,41 @@ already reserved for subject labels).
The descriptions on the [labels page][labels-page] explain what falls under each type label. The descriptions on the [labels page][labels-page] explain what falls under each type label.
### Subject labels (~wiki, ~"container registry", ~ldap, ~api, etc.) ### Subject labels
Subject labels are labels that define what area or feature of GitLab this issue Subject labels are labels that define what area or feature of GitLab this issue
hits. They are not always necessary, but very convenient. hits. They are not always necessary, but very convenient.
Examples of subject labels are ~wiki, ~ldap, ~api,
~issues, ~"merge requests", ~labels, and ~"container registry".
If you are an expert in a particular area, it makes it easier to find issues to If you are an expert in a particular area, it makes it easier to find issues to
work on. You can also subscribe to those labels to receive an email each time an work on. You can also subscribe to those labels to receive an email each time an
issue is labelled with a subject label corresponding to your expertise. issue is labeled with a subject label corresponding to your expertise.
Examples of subject labels are ~wiki, ~"container registry", ~ldap, ~api,
~issues, ~"merge requests", ~labels, and ~"container registry".
Subject labels are always all-lowercase. Subject labels are always all-lowercase.
### Team labels (~"CI/CD", ~Discussion, ~Quality, ~Platform, etc.) ### Team labels
Team labels specify what team is responsible for this issue. Team labels specify what team is responsible for this issue.
Assigning a team label makes sure issues get the attention of the appropriate Assigning a team label makes sure issues get the attention of the appropriate
people. people.
The current team labels are ~Build, ~"CI/CD", ~Discussion, ~Documentation, ~Quality, The current team labels are:
~Geo, ~Gitaly, ~Monitoring, ~Platform, ~Release, ~"Security Products" and ~"UX".
- ~Configuration
- ~"CI/CD"
- ~Discussion
- ~Distribution
- ~Documentation
- ~Geo
- ~Gitaly
- ~Monitoring
- ~Platform
- ~Quality
- ~Release
- ~"Security Products"
- ~UX
The descriptions on the [labels page][labels-page] explain what falls under the The descriptions on the [labels page][labels-page] explain what falls under the
responsibility of each team. responsibility of each team.
@ -193,10 +207,10 @@ indicate if an issue needs backend work, frontend work, or both.
Team labels are always capitalized so that they show up as the first label for Team labels are always capitalized so that they show up as the first label for
any issue. any issue.
### Milestone labels (~Deliverable, ~Stretch, ~"Next Patch Release") ### Release Scoping labels
Milestone labels help us clearly communicate expectations of the work for the Release Scoping labels help us clearly communicate expectations of the work for the
release. There are three levels of Milestone labels: release. There are three levels of Release Scoping labels:
- ~Deliverable: Issues that are expected to be delivered in the current - ~Deliverable: Issues that are expected to be delivered in the current
milestone. milestone.
@ -211,9 +225,10 @@ Each issue scheduled for the current milestone should be labeled ~Deliverable
or ~"Stretch". Any open issue for a previous milestone should be labeled or ~"Stretch". Any open issue for a previous milestone should be labeled
~"Next Patch Release", or otherwise rescheduled to a different milestone. ~"Next Patch Release", or otherwise rescheduled to a different milestone.
### Bug Priority labels (~P1, ~P2, ~P3 & etc.) ### Bug Priority labels
Bug Priority labels help us define the time a ~bug fix should be completed. Priority determines how quickly the defect turnaround time must be. If there are multiple defects, the priority decides which defect has to be fixed immediately versus later. Bug Priority labels help us define the time a ~bug fix should be completed. Priority determines how quickly the defect turnaround time must be.
If there are multiple defects, the priority decides which defect has to be fixed immediately versus later.
This label documents the planned timeline & urgency which is used to measure against our actual SLA on delivering ~bug fixes. This label documents the planned timeline & urgency which is used to measure against our actual SLA on delivering ~bug fixes.
| Label | Meaning | Estimate time to fix | Guidance | | Label | Meaning | Estimate time to fix | Guidance |
@ -223,16 +238,7 @@ This label documents the planned timeline & urgency which is used to measure aga
| ~P3 | Medium Priority | Within the next 3 releases (approx one quarter) | | | ~P3 | Medium Priority | Within the next 3 releases (approx one quarter) | |
| ~P4 | Low Priority | Anything outside the next 3 releases (approx beyond one quarter) | The issue is prominent but does not impact user workflow and a workaround is documented | | ~P4 | Low Priority | Anything outside the next 3 releases (approx beyond one quarter) | The issue is prominent but does not impact user workflow and a workaround is documented |
#### Specific Priority guidance ### Bug Severity labels
| Label | Availability / Performance |
|-------|--------------------------------------------------------------|
| ~P1 | |
| ~P2 | The issue is (almost) guaranteed to occur in the near future |
| ~P3 | The issue is likely to occur in the near future |
| ~P4 | The issue _may_ occur but it's not likely |
### Bug Severity labels (~S1, ~S2, ~S3 & etc.)
Severity labels help us clearly communicate the impact of a ~bug on users. Severity labels help us clearly communicate the impact of a ~bug on users.
@ -243,16 +249,16 @@ Severity labels help us clearly communicate the impact of a ~bug on users.
| ~S3 | Major Severity | Broken Feature, workaround acceptable | Can create merge requests only from the Merge Requests page, not through the Issue. | | ~S3 | Major Severity | Broken Feature, workaround acceptable | Can create merge requests only from the Merge Requests page, not through the Issue. |
| ~S4 | Low Severity | Functionality inconvenience or cosmetic issue | Label colors are incorrect / not being displayed. | | ~S4 | Low Severity | Functionality inconvenience or cosmetic issue | Label colors are incorrect / not being displayed. |
#### Specific Severity guidance #### Severity impact guidance
| Label | Security Impact | | Label | Security Impact | Availability / Performance Impact |
|-------|-------------------------------------------------------------------| |-------|---------------------------------------------------------------------|--------------------------------------------------------------|
| ~S1 | >50% customers impacted (possible company extinction level event) | | ~S1 | >50% users impacted (possible company extinction level event) | |
| ~S2 | Multiple customers impacted (but not apocalyptic) | | ~S2 | Many users or multiple paid customers impacted (but not apocalyptic)| The issue is (almost) guaranteed to occur in the near future |
| ~S3 | A single customer impacted | | ~S3 | A few users or a single paid customer impacted | The issue is likely to occur in the near future |
| ~S4 | No customer impact, or expected impact within 30 days | | ~S4 | No paid users/customer impacted, or expected impact within 30 days | The issue _may_ occur but it's not likely |
### Label for community contributors (~"Accepting Merge Requests") ### Label for community contributors
Issues that are beneficial to our users, 'nice to haves', that we currently do Issues that are beneficial to our users, 'nice to haves', that we currently do
not have the capacity for or want to give the priority to, are labeled as not have the capacity for or want to give the priority to, are labeled as
@ -304,7 +310,33 @@ any potential community contributor to @-mention per above.
## Implement design & UI elements ## Implement design & UI elements
Please see the [UX Guide for GitLab]. For guidance on UX implementation at GitLab, please refer to our [Design System](https://design.gitlab.com/).
The UX team uses labels to manage their workflow.
The ~"UX" label on an issue is a signal to the UX team that it will need UX attention.
To better understand the priority by which UX tackles issues, see the [UX section](https://about.gitlab.com/handbook/engineering/ux) of the handbook.
Once an issue has been worked on and is ready for development, a UXer removes the ~"UX" label and applies the ~"UX ready" label to that issue.
The UX team has a special type label called ~"design artifact". This label indicates that the final output
for an issue is a UX solution/design. The solution will be developed by frontend and/or backend in a subsequent milestone.
Any issue labeled ~"design artifact" should not also be labeled ~"frontend" or ~"backend" since no development is
needed until the solution has been decided.
~"design artifact" issues are like any other issue and should contain a milestone label, ~"Deliverable" or ~"Stretch", when scheduled in the current milestone.
To prevent the misunderstanding that a feature will be be delivered in the
assigned milestone, when only UX design is planned for that milestone, the
Product Manager should create a separate issue for the ~"design artifact",
assign the ~UX, ~"design artifact" and ~"Deliverable" labels, add a milestone
and use a title that makes it clear that the scheduled issue is design only
(e.g. `Design exploration for XYZ`).
When the ~"design artifact" issue has been completed, the UXer removes the ~UX
label, adds the ~"UX ready" label and closes the issue. This indicates the
design artifact is complete. The UXer will also copy the designs to related
issues for implementation in an upcoming milestone.
## Issue tracker ## Issue tracker
@ -340,7 +372,7 @@ on those issues. Please select someone with relevant experience from the
[GitLab team][team]. If there is nobody mentioned with that expertise look in [GitLab team][team]. If there is nobody mentioned with that expertise look in
the commit history for the affected files to find someone. the commit history for the affected files to find someone.
[described in our handbook]: https://about.gitlab.com/handbook/engineering/issues/issue-triage-policies/ [described in our handbook]: https://about.gitlab.com/handbook/engineering/issue-triage/
[issue bash events]: https://gitlab.com/gitlab-org/gitlab-ce/issues/17815 [issue bash events]: https://gitlab.com/gitlab-org/gitlab-ce/issues/17815
### Feature proposals ### Feature proposals
@ -503,7 +535,7 @@ request is as follows:
1. Write [tests](https://docs.gitlab.com/ee/development/rake_tasks.html#run-tests) and code 1. Write [tests](https://docs.gitlab.com/ee/development/rake_tasks.html#run-tests) and code
1. [Generate a changelog entry with `bin/changelog`][changelog] 1. [Generate a changelog entry with `bin/changelog`][changelog]
1. If you are writing documentation, make sure to follow the 1. If you are writing documentation, make sure to follow the
[documentation styleguide][doc-styleguide] [documentation guidelines][doc-guidelines]
1. If you have multiple commits please combine them into a few logically 1. If you have multiple commits please combine them into a few logically
organized commits by [squashing them][git-squash] organized commits by [squashing them][git-squash]
1. Push the commit(s) to your fork 1. Push the commit(s) to your fork
@ -618,7 +650,7 @@ the feature you contribute through all of these steps.
1. Working and clean code that is commented where needed 1. Working and clean code that is commented where needed
1. [Unit, integration, and system tests][testing] that pass on the CI server 1. [Unit, integration, and system tests][testing] that pass on the CI server
1. Performance/scalability implications have been considered, addressed, and tested 1. Performance/scalability implications have been considered, addressed, and tested
1. [Documented][doc-styleguide] in the `/doc` directory 1. [Documented][doc-guidelines] in the `/doc` directory
1. [Changelog entry added][changelog], if necessary 1. [Changelog entry added][changelog], if necessary
1. Reviewed and any concerns are addressed 1. Reviewed and any concerns are addressed
1. Merged by a project maintainer 1. Merged by a project maintainer
@ -655,7 +687,7 @@ merge request:
contributors to enhance security contributors to enhance security
1. [Database Migrations](doc/development/migration_style_guide.md) 1. [Database Migrations](doc/development/migration_style_guide.md)
1. [Markdown](http://www.cirosantilli.com/markdown-styleguide) 1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
1. [Documentation styleguide][doc-styleguide] 1. [Documentation styleguide](https://docs.gitlab.com/ee/development/documentation/styleguide.html)
1. Interface text should be written subjectively instead of objectively. It 1. Interface text should be written subjectively instead of objectively. It
should be the GitLab core team addressing a person. It should be written in should be the GitLab core team addressing a person. It should be written in
present time and never use past tense (has been/was). For example instead present time and never use past tense (has been/was). For example instead
@ -718,7 +750,7 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
[rss-source]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#source-code-layout [rss-source]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#source-code-layout
[rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming [rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming
[changelog]: doc/development/changelog.md "Generate a changelog entry" [changelog]: doc/development/changelog.md "Generate a changelog entry"
[doc-styleguide]: doc/development/doc_styleguide.md "Documentation styleguide" [doc-guidelines]: doc/development/documentation/index.md "Documentation guidelines"
[js-styleguide]: doc/development/fe_guide/style_guide_js.md "JavaScript styleguide" [js-styleguide]: doc/development/fe_guide/style_guide_js.md "JavaScript styleguide"
[scss-styleguide]: doc/development/fe_guide/style_guide_scss.md "SCSS styleguide" [scss-styleguide]: doc/development/fe_guide/style_guide_scss.md "SCSS styleguide"
[newlines-styleguide]: doc/development/newlines_styleguide.md "Newlines styleguide" [newlines-styleguide]: doc/development/newlines_styleguide.md "Newlines styleguide"
@ -728,6 +760,3 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
[polling-etag]: https://docs.gitlab.com/ce/development/polling.html [polling-etag]: https://docs.gitlab.com/ce/development/polling.html
[testing]: doc/development/testing_guide/index.md [testing]: doc/development/testing_guide/index.md
[us-english]: https://en.wikipedia.org/wiki/American_English [us-english]: https://en.wikipedia.org/wiki/American_English
[^1]: Please note that specs other than JavaScript specs are considered backend
code.

View file

@ -1 +1 @@
0.100.1 0.111.4

View file

@ -1 +1 @@
0.9.1 1.0.0

View file

@ -1 +1 @@
7.1.2 7.1.4

View file

@ -1 +1 @@
4.2.1 5.0.0

62
Gemfile
View file

@ -6,7 +6,7 @@ end
gem_versions = {} gem_versions = {}
gem_versions['activerecord_sane_schema_dumper'] = rails5? ? '1.0' : '0.2' gem_versions['activerecord_sane_schema_dumper'] = rails5? ? '1.0' : '0.2'
gem_versions['default_value_for'] = rails5? ? '~> 3.0.5' : '~> 3.0.0' gem_versions['default_value_for'] = rails5? ? '~> 3.0.5' : '~> 3.0.0'
gem_versions['rails'] = rails5? ? '5.0.6' : '4.2.10' gem_versions['rails'] = rails5? ? '5.0.7' : '4.2.10'
gem_versions['rails-i18n'] = rails5? ? '~> 5.1' : '~> 4.0.9' gem_versions['rails-i18n'] = rails5? ? '~> 5.1' : '~> 4.0.9'
# --- The end of special code for migrating to Rails 5.0 --- # --- The end of special code for migrating to Rails 5.0 ---
@ -28,14 +28,14 @@ gem 'mysql2', '~> 0.4.10', group: :mysql
gem 'pg', '~> 0.18.2', group: :postgres gem 'pg', '~> 0.18.2', group: :postgres
gem 'rugged', '~> 0.27' gem 'rugged', '~> 0.27'
gem 'grape-route-helpers', '~> 2.1.0' gem 'grape-path-helpers', '~> 1.0'
gem 'faraday', '~> 0.12' gem 'faraday', '~> 0.12'
# Authentication libraries # Authentication libraries
gem 'devise', '~> 4.4' gem 'devise', '~> 4.4'
gem 'doorkeeper', '~> 4.3' gem 'doorkeeper', '~> 4.3'
gem 'doorkeeper-openid_connect', '~> 1.3' gem 'doorkeeper-openid_connect', '~> 1.5'
gem 'omniauth', '~> 1.8' gem 'omniauth', '~> 1.8'
gem 'omniauth-auth0', '~> 2.0.0' gem 'omniauth-auth0', '~> 2.0.0'
gem 'omniauth-azure-oauth2', '~> 0.0.9' gem 'omniauth-azure-oauth2', '~> 0.0.9'
@ -47,10 +47,10 @@ gem 'omniauth-google-oauth2', '~> 0.5.3'
gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos
gem 'omniauth-oauth2-generic', '~> 0.2.2' gem 'omniauth-oauth2-generic', '~> 0.2.2'
gem 'omniauth-saml', '~> 1.10' gem 'omniauth-saml', '~> 1.10'
gem 'omniauth-shibboleth', '~> 1.2.0' gem 'omniauth-shibboleth', '~> 1.3.0'
gem 'omniauth-twitter', '~> 1.4' gem 'omniauth-twitter', '~> 1.4'
gem 'omniauth_crowd', '~> 2.2.0' gem 'omniauth_crowd', '~> 2.2.0'
gem 'omniauth-authentiq', '~> 0.3.1' gem 'omniauth-authentiq', '~> 0.3.3'
gem 'rack-oauth2', '~> 1.2.1' gem 'rack-oauth2', '~> 1.2.1'
gem 'jwt', '~> 1.5.6' gem 'jwt', '~> 1.5.6'
@ -93,6 +93,10 @@ gem 'grape', '~> 1.0'
gem 'grape-entity', '~> 0.7.1' gem 'grape-entity', '~> 0.7.1'
gem 'rack-cors', '~> 1.0.0', require: 'rack/cors' gem 'rack-cors', '~> 1.0.0', require: 'rack/cors'
# GraphQL API
gem 'graphql', '~> 1.8.0'
gem 'graphiql-rails', '~> 1.4.10'
# Disable strong_params so that Mash does not respond to :permitted? # Disable strong_params so that Mash does not respond to :permitted?
gem 'hashie-forbidden_attributes' gem 'hashie-forbidden_attributes'
@ -104,6 +108,7 @@ gem 'hamlit', '~> 2.6.1'
# Files attachments # Files attachments
gem 'carrierwave', '~> 1.2' gem 'carrierwave', '~> 1.2'
gem 'mini_magick'
# Drag and Drop UI # Drag and Drop UI
gem 'dropzonejs-rails', '~> 0.7.1' gem 'dropzonejs-rails', '~> 0.7.1'
@ -127,13 +132,13 @@ gem 'unf', '~> 0.1.4'
gem 'seed-fu', '~> 2.3.7' gem 'seed-fu', '~> 2.3.7'
# Markdown and HTML processing # Markdown and HTML processing
gem 'html-pipeline', '~> 2.7.1' gem 'html-pipeline', '~> 2.8'
gem 'deckar01-task_list', '2.0.0' gem 'deckar01-task_list', '2.0.0'
gem 'gitlab-markup', '~> 1.6.2' gem 'gitlab-markup', '~> 1.6.4'
gem 'redcarpet', '~> 3.4' gem 'redcarpet', '~> 3.4'
gem 'commonmarker', '~> 0.17' gem 'commonmarker', '~> 0.17'
gem 'RedCloth', '~> 4.3.2' gem 'RedCloth', '~> 4.3.2'
gem 'rdoc', '~> 4.2' gem 'rdoc', '~> 6.0'
gem 'org-ruby', '~> 0.9.12' gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~> 0.5.0' gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1' gem 'wikicloth', '0.8.1'
@ -144,6 +149,9 @@ gem 'truncato', '~> 0.7.9'
gem 'bootstrap_form', '~> 2.7.0' gem 'bootstrap_form', '~> 2.7.0'
gem 'nokogiri', '~> 1.8.2' gem 'nokogiri', '~> 1.8.2'
# Calendar rendering
gem 'icalendar'
# Diffs # Diffs
gem 'diffy', '~> 3.1.0' gem 'diffy', '~> 3.1.0'
@ -160,9 +168,9 @@ gem 'state_machines-activerecord', '~> 0.5.1'
gem 'acts-as-taggable-on', '~> 5.0' gem 'acts-as-taggable-on', '~> 5.0'
# Background jobs # Background jobs
gem 'sidekiq', '~> 5.0' gem 'sidekiq', '~> 5.1'
gem 'sidekiq-cron', '~> 0.6.0' gem 'sidekiq-cron', '~> 0.6.0'
gem 'redis-namespace', '~> 1.5.2' gem 'redis-namespace', '~> 1.6.0'
gem 'sidekiq-limit_fetch', '~> 3.4', require: false gem 'sidekiq-limit_fetch', '~> 3.4', require: false
# Cron Parser # Cron Parser
@ -174,6 +182,9 @@ gem 'httparty', '~> 0.13.3'
# Colored output to console # Colored output to console
gem 'rainbow', '~> 2.2' gem 'rainbow', '~> 2.2'
# Progress bar
gem 'ruby-progressbar'
# GitLab settings # GitLab settings
gem 'settingslogic', '~> 2.0.9' gem 'settingslogic', '~> 2.0.9'
@ -216,10 +227,7 @@ gem 'asana', '~> 0.6.0'
gem 'ruby-fogbugz', '~> 0.2.1' gem 'ruby-fogbugz', '~> 0.2.1'
# Kubernetes integration # Kubernetes integration
gem 'kubeclient', '~> 3.0' gem 'kubeclient', '~> 3.1.0'
# d3
gem 'd3_rails', '~> 3.5.0'
# Sanitize user input # Sanitize user input
gem 'sanitize', '~> 4.6.5' gem 'sanitize', '~> 4.6.5'
@ -257,10 +265,9 @@ gem 'sass-rails', '~> 5.0.6'
gem 'uglifier', '~> 2.7.2' gem 'uglifier', '~> 2.7.2'
gem 'addressable', '~> 2.5.2' gem 'addressable', '~> 2.5.2'
gem 'bootstrap-sass', '~> 3.3.0'
gem 'font-awesome-rails', '~> 4.7' gem 'font-awesome-rails', '~> 4.7'
gem 'gemojione', '~> 3.3' gem 'gemojione', '~> 3.3'
gem 'gon', '~> 6.1.0' gem 'gon', '~> 6.2'
gem 'jquery-atwho-rails', '~> 1.3.2' gem 'jquery-atwho-rails', '~> 1.3.2'
gem 'request_store', '~> 1.3' gem 'request_store', '~> 1.3'
gem 'select2-rails', '~> 3.5.9' gem 'select2-rails', '~> 3.5.9'
@ -292,7 +299,6 @@ gem 'peek-sidekiq', '~> 1.0.3'
# Metrics # Metrics
group :metrics do group :metrics do
gem 'allocations', '~> 1.0', require: false, platform: :mri
gem 'method_source', '~> 0.8', require: false gem 'method_source', '~> 0.8', require: false
gem 'influxdb', '~> 0.2', require: false gem 'influxdb', '~> 0.2', require: false
@ -321,15 +327,13 @@ group :development, :test do
gem 'pry-byebug', '~> 3.4.1', platform: :mri gem 'pry-byebug', '~> 3.4.1', platform: :mri
gem 'pry-rails', '~> 0.3.4' gem 'pry-rails', '~> 0.3.4'
gem 'awesome_print', '~> 1.2.0', require: false gem 'awesome_print', require: false
gem 'fuubar', '~> 2.2.0' gem 'fuubar', '~> 2.2.0'
gem 'database_cleaner', '~> 1.5.0' gem 'database_cleaner', '~> 1.5.0'
gem 'factory_bot_rails', '~> 4.8.2' gem 'factory_bot_rails', '~> 4.8.2'
gem 'rspec-rails', '~> 3.6.0' gem 'rspec-rails', '~> 3.7.0'
gem 'rspec-retry', '~> 0.4.5' gem 'rspec-retry', '~> 0.4.5'
gem 'spinach-rails', '~> 0.2.1'
gem 'spinach-rerun-reporter', '~> 0.0.2'
gem 'rspec_profiling', '~> 0.0.5' gem 'rspec_profiling', '~> 0.0.5'
gem 'rspec-set', '~> 0.1.3' gem 'rspec-set', '~> 0.1.3'
gem 'rspec-parameterized', require: false gem 'rspec-parameterized', require: false
@ -342,11 +346,10 @@ group :development, :test do
gem 'capybara', '~> 2.15' gem 'capybara', '~> 2.15'
gem 'capybara-screenshot', '~> 1.0.0' gem 'capybara-screenshot', '~> 1.0.0'
gem 'selenium-webdriver', '~> 3.5' gem 'selenium-webdriver', '~> 3.12'
gem 'spring', '~> 2.0.0' gem 'spring', '~> 2.0.0'
gem 'spring-commands-rspec', '~> 1.0.4' gem 'spring-commands-rspec', '~> 1.0.4'
gem 'spring-commands-spinach', '~> 1.1.0'
gem 'gitlab-styles', '~> 2.3', require: false gem 'gitlab-styles', '~> 2.3', require: false
# Pin these dependencies, otherwise a new rule could break the CI pipelines # Pin these dependencies, otherwise a new rule could break the CI pipelines
@ -375,7 +378,7 @@ end
group :test do group :test do
gem 'shoulda-matchers', '~> 3.1.2', require: false gem 'shoulda-matchers', '~> 3.1.2', require: false
gem 'email_spec', '~> 1.6.0' gem 'email_spec', '~> 2.2.0'
gem 'json-schema', '~> 2.8.0' gem 'json-schema', '~> 2.8.0'
gem 'webmock', '~> 2.3.2' gem 'webmock', '~> 2.3.2'
gem 'rails-controller-testing' if rails5? # Rails5 only gem. gem 'rails-controller-testing' if rails5? # Rails5 only gem.
@ -385,7 +388,7 @@ group :test do
gem 'test-prof', '~> 0.2.5' gem 'test-prof', '~> 0.2.5'
end end
gem 'octokit', '~> 4.8' gem 'octokit', '~> 4.9'
gem 'mail_room', '~> 0.9.1' gem 'mail_room', '~> 0.9.1'
@ -405,18 +408,17 @@ gem 'vmstat', '~> 2.3.0'
gem 'sys-filesystem', '~> 1.1.6' gem 'sys-filesystem', '~> 1.1.6'
# SSH host key support # SSH host key support
gem 'net-ssh', '~> 4.2.0' gem 'net-ssh', '~> 5.0'
gem 'sshkey', '~> 1.9.0' gem 'sshkey', '~> 1.9.0'
# Required for ED25519 SSH host key support # Required for ED25519 SSH host key support
group :ed25519 do group :ed25519 do
gem 'rbnacl-libsodium' gem 'ed25519', '~> 1.2'
gem 'rbnacl', '~> 4.0'
gem 'bcrypt_pbkdf', '~> 1.0' gem 'bcrypt_pbkdf', '~> 1.0'
end end
# Gitaly GRPC client # Gitaly GRPC client
gem 'gitaly-proto', '~> 0.99.0', require: 'gitaly' gem 'gitaly-proto', '~> 0.105.0', require: 'gitaly'
gem 'grpc', '~> 1.11.0' gem 'grpc', '~> 1.11.0'
# Locked until https://github.com/google/protobuf/issues/4210 is closed # Locked until https://github.com/google/protobuf/issues/4210 is closed
@ -434,4 +436,4 @@ gem 'lograge', '~> 0.5'
gem 'grape_logging', '~> 1.7' gem 'grape_logging', '~> 1.7'
# Asset synchronization # Asset synchronization
gem 'asset_sync', '~> 2.2.0' gem 'asset_sync', '~> 2.4'

View file

@ -49,7 +49,6 @@ GEM
public_suffix (>= 2.0.2, < 4.0) public_suffix (>= 2.0.2, < 4.0)
aes_key_wrap (1.0.1) aes_key_wrap (1.0.1)
akismet (2.0.0) akismet (2.0.0)
allocations (1.0.5)
arel (6.0.4) arel (6.0.4)
asana (0.6.0) asana (0.6.0)
faraday (~> 0.9) faraday (~> 0.9)
@ -59,7 +58,7 @@ GEM
asciidoctor (1.5.6.2) asciidoctor (1.5.6.2)
asciidoctor-plantuml (0.0.8) asciidoctor-plantuml (0.0.8)
asciidoctor (~> 1.5) asciidoctor (~> 1.5)
asset_sync (2.2.0) asset_sync (2.4.0)
activemodel (>= 4.1.0) activemodel (>= 4.1.0)
fog-core fog-core
mime-types (>= 2.99) mime-types (>= 2.99)
@ -69,10 +68,7 @@ GEM
attr_encrypted (3.1.0) attr_encrypted (3.1.0)
encryptor (~> 3.0.0) encryptor (~> 3.0.0)
attr_required (1.0.0) attr_required (1.0.0)
autoprefixer-rails (6.2.3) awesome_print (1.8.0)
execjs
json
awesome_print (1.2.0)
axiom-types (0.1.1) axiom-types (0.1.1)
descendants_tracker (~> 0.0.4) descendants_tracker (~> 0.0.4)
ice_nine (~> 0.11.0) ice_nine (~> 0.11.0)
@ -80,7 +76,7 @@ GEM
babosa (1.0.2) babosa (1.0.2)
base32 (0.3.2) base32 (0.3.2)
batch-loader (1.2.1) batch-loader (1.2.1)
bcrypt (3.1.11) bcrypt (3.1.12)
bcrypt_pbkdf (1.0.0) bcrypt_pbkdf (1.0.0)
benchmark-ips (2.3.0) benchmark-ips (2.3.0)
better_errors (2.1.1) better_errors (2.1.1)
@ -91,9 +87,6 @@ GEM
binding_of_caller (0.7.2) binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
blankslate (2.1.2.4) blankslate (2.1.2.4)
bootstrap-sass (3.3.6)
autoprefixer-rails (>= 5.2.1)
sass (>= 3.3.4)
bootstrap_form (2.7.0) bootstrap_form (2.7.0)
brakeman (4.2.1) brakeman (4.2.1)
browser (2.2.0) browser (2.2.0)
@ -115,13 +108,13 @@ GEM
capybara-screenshot (1.0.14) capybara-screenshot (1.0.14)
capybara (>= 1.0, < 3) capybara (>= 1.0, < 3)
launchy launchy
carrierwave (1.2.1) carrierwave (1.2.3)
activemodel (>= 4.0.0) activemodel (>= 4.0.0)
activesupport (>= 4.0.0) activesupport (>= 4.0.0)
mime-types (>= 1.16) mime-types (>= 1.16)
cause (0.1) cause (0.1)
charlock_holmes (0.7.6) charlock_holmes (0.7.6)
childprocess (0.7.0) childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11) ffi (~> 1.0, >= 1.0.11)
chronic (0.10.2) chronic (0.10.2)
chronic_duration (0.10.6) chronic_duration (0.10.6)
@ -131,7 +124,6 @@ GEM
coderay (1.1.1) coderay (1.1.1)
coercible (1.0.0) coercible (1.0.0)
descendants_tracker (~> 0.0.1) descendants_tracker (~> 0.0.1)
colorize (0.7.7)
commonmarker (0.17.8) commonmarker (0.17.8)
ruby-enum (~> 0.5) ruby-enum (~> 0.5)
concord (0.1.5) concord (0.1.5)
@ -147,8 +139,6 @@ GEM
creole (0.5.0) creole (0.5.0)
css_parser (1.5.0) css_parser (1.5.0)
addressable addressable
d3_rails (3.5.11)
railties (>= 3.1.0)
daemons (1.2.3) daemons (1.2.3)
database_cleaner (1.5.3) database_cleaner (1.5.3)
debug_inspector (0.0.2) debug_inspector (0.0.2)
@ -177,19 +167,21 @@ GEM
diff-lcs (1.3) diff-lcs (1.3)
diffy (3.1.0) diffy (3.1.0)
docile (1.1.5) docile (1.1.5)
domain_name (0.5.20170404) domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
doorkeeper (4.3.2) doorkeeper (4.3.2)
railties (>= 4.2) railties (>= 4.2)
doorkeeper-openid_connect (1.3.0) doorkeeper-openid_connect (1.5.0)
doorkeeper (~> 4.3) doorkeeper (~> 4.3)
json-jwt (~> 1.6) json-jwt (~> 1.6)
dropzonejs-rails (0.7.2) dropzonejs-rails (0.7.2)
rails (> 3.1) rails (> 3.1)
ed25519 (1.2.4)
email_reply_trimmer (0.1.6) email_reply_trimmer (0.1.6)
email_spec (1.6.0) email_spec (2.2.0)
htmlentities (~> 4.3.3)
launchy (~> 2.1) launchy (~> 2.1)
mail (~> 2.2) mail (~> 2.7)
encryptor (3.0.0) encryptor (3.0.0)
equalizer (0.0.11) equalizer (0.0.11)
erubis (2.7.0) erubis (2.7.0)
@ -197,7 +189,7 @@ GEM
et-orbi (1.0.3) et-orbi (1.0.3)
tzinfo tzinfo
eventmachine (1.0.8) eventmachine (1.0.8)
excon (0.60.0) excon (0.62.0)
execjs (2.6.0) execjs (2.6.0)
expression_parser (0.9.0) expression_parser (0.9.0)
factory_bot (4.8.2) factory_bot (4.8.2)
@ -290,8 +282,7 @@ GEM
gettext_i18n_rails (>= 0.7.1) gettext_i18n_rails (>= 0.7.1)
po_to_json (>= 1.0.0) po_to_json (>= 1.0.0)
rails (>= 3.2.0) rails (>= 3.2.0)
gherkin-ruby (0.3.2) gitaly-proto (0.105.0)
gitaly-proto (0.99.0)
google-protobuf (~> 3.1) google-protobuf (~> 3.1)
grpc (~> 1.10) grpc (~> 1.10)
github-linguist (5.3.3) github-linguist (5.3.3)
@ -312,7 +303,7 @@ GEM
rouge (~> 3.1) rouge (~> 3.1)
sanitize (~> 4.6.4) sanitize (~> 4.6.4)
stringex (~> 2.6) stringex (~> 2.6)
gitlab-gollum-rugged_adapter (0.4.4) gitlab-gollum-rugged_adapter (0.4.4.1)
mime-types (>= 1.15) mime-types (>= 1.15)
rugged (~> 0.25) rugged (~> 0.25)
gitlab-grit (2.8.2) gitlab-grit (2.8.2)
@ -320,7 +311,7 @@ GEM
diff-lcs (~> 1.1) diff-lcs (~> 1.1)
mime-types (>= 1.16) mime-types (>= 1.16)
posix-spawn (~> 0.3) posix-spawn (~> 0.3)
gitlab-markup (1.6.3) gitlab-markup (1.6.4)
gitlab-styles (2.3.2) gitlab-styles (2.3.2)
rubocop (~> 0.51) rubocop (~> 0.51)
rubocop-gitlab-security (~> 0.1.0) rubocop-gitlab-security (~> 0.1.0)
@ -334,9 +325,8 @@ GEM
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
gollum-grit_adapter (1.0.1) gollum-grit_adapter (1.0.1)
gitlab-grit (~> 2.7, >= 2.7.1) gitlab-grit (~> 2.7, >= 2.7.1)
gon (6.1.0) gon (6.2.0)
actionpack (>= 3.0) actionpack (>= 3.0)
json
multi_json multi_json
request_store (>= 1.0) request_store (>= 1.0)
google-api-client (0.19.8) google-api-client (0.19.8)
@ -359,7 +349,7 @@ GEM
signet (~> 0.7) signet (~> 0.7)
gpgme (2.0.13) gpgme (2.0.13)
mini_portile2 (~> 2.1) mini_portile2 (~> 2.1)
grape (1.0.2) grape (1.0.3)
activesupport activesupport
builder builder
mustermann-grape (~> 1.0.0) mustermann-grape (~> 1.0.0)
@ -369,12 +359,16 @@ GEM
grape-entity (0.7.1) grape-entity (0.7.1)
activesupport (>= 4.0) activesupport (>= 4.0)
multi_json (>= 1.3.2) multi_json (>= 1.3.2)
grape-route-helpers (2.1.0) grape-path-helpers (1.0.5)
activesupport activesupport (>= 4, < 5.1)
grape (>= 0.16.0) grape (~> 1.0)
rake rake (~> 12)
grape_logging (1.7.0) grape_logging (1.7.0)
grape grape
graphiql-rails (1.4.10)
railties
sprockets-rails
graphql (1.8.1)
grpc (1.11.0) grpc (1.11.0)
google-protobuf (~> 3.1) google-protobuf (~> 3.1)
googleapis-common-protos-types (~> 1.0.0) googleapis-common-protos-types (~> 1.0.0)
@ -400,7 +394,7 @@ GEM
hipchat (1.5.2) hipchat (1.5.2)
httparty httparty
mimemagic mimemagic
html-pipeline (2.7.1) html-pipeline (2.8.3)
activesupport (>= 2) activesupport (>= 2)
nokogiri (>= 1.4) nokogiri (>= 1.4)
html2text (0.2.0) html2text (0.2.0)
@ -421,6 +415,7 @@ GEM
httpclient (2.8.3) httpclient (2.8.3)
i18n (0.9.5) i18n (0.9.5)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
icalendar (2.4.1)
ice_nine (0.11.2) ice_nine (0.11.2)
influxdb (0.2.3) influxdb (0.2.3)
cause cause
@ -432,12 +427,10 @@ GEM
oauth (~> 0.5, >= 0.5.0) oauth (~> 0.5, >= 0.5.0)
jquery-atwho-rails (1.3.2) jquery-atwho-rails (1.3.2)
json (1.8.6) json (1.8.6)
json-jwt (1.9.2) json-jwt (1.9.4)
activesupport activesupport
aes_key_wrap aes_key_wrap
bindata bindata
securecompare
url_safe_base64
json-schema (2.8.0) json-schema (2.8.0)
addressable (>= 2.4) addressable (>= 2.4)
jwt (1.5.6) jwt (1.5.6)
@ -456,10 +449,9 @@ GEM
kgio (2.10.0) kgio (2.10.0)
knapsack (1.16.0) knapsack (1.16.0)
rake rake
timecop (>= 0.1.0) kubeclient (3.1.0)
kubeclient (3.0.0)
http (~> 2.2.2) http (~> 2.2.2)
recursive-open-struct (~> 1.0.4) recursive-open-struct (~> 1.0, >= 1.0.4)
rest-client (~> 2.0) rest-client (~> 2.0)
launchy (2.4.3) launchy (2.4.3)
addressable (~> 2.3) addressable (~> 2.3)
@ -503,6 +495,7 @@ GEM
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521) mime-types-data (3.2016.0521)
mimemagic (0.3.0) mimemagic (0.3.0)
mini_magick (4.8.0)
mini_mime (1.0.0) mini_mime (1.0.0)
mini_portile2 (2.3.0) mini_portile2 (2.3.0)
minitest (5.7.0) minitest (5.7.0)
@ -515,9 +508,9 @@ GEM
mustermann (~> 1.0.0) mustermann (~> 1.0.0)
mysql2 (0.4.10) mysql2 (0.4.10)
net-ldap (0.16.0) net-ldap (0.16.0)
net-ssh (4.2.0) net-ssh (5.0.1)
netrc (0.11.0) netrc (0.11.0)
nokogiri (1.8.2) nokogiri (1.8.3)
mini_portile2 (~> 2.3.0) mini_portile2 (~> 2.3.0)
nokogumbo (1.5.0) nokogumbo (1.5.0)
nokogiri nokogiri
@ -529,15 +522,16 @@ GEM
multi_json (~> 1.3) multi_json (~> 1.3)
multi_xml (~> 0.5) multi_xml (~> 0.5)
rack (>= 1.2, < 3) rack (>= 1.2, < 3)
octokit (4.8.0) octokit (4.9.0)
sawyer (~> 0.8.0, >= 0.5.3) sawyer (~> 0.8.0, >= 0.5.3)
omniauth (1.8.1) omniauth (1.8.1)
hashie (>= 3.4.6, < 3.6.0) hashie (>= 3.4.6, < 3.6.0)
rack (>= 1.6.2, < 3) rack (>= 1.6.2, < 3)
omniauth-auth0 (2.0.0) omniauth-auth0 (2.0.0)
omniauth-oauth2 (~> 1.4) omniauth-oauth2 (~> 1.4)
omniauth-authentiq (0.3.1) omniauth-authentiq (0.3.3)
omniauth-oauth2 (~> 1.3, >= 1.3.1) jwt (>= 1.5)
omniauth-oauth2 (>= 1.5)
omniauth-azure-oauth2 (0.0.9) omniauth-azure-oauth2 (0.0.9)
jwt (~> 1.0) jwt (~> 1.0)
omniauth (~> 1.0) omniauth (~> 1.0)
@ -551,7 +545,7 @@ GEM
omniauth-github (1.3.0) omniauth-github (1.3.0)
omniauth (~> 1.5) omniauth (~> 1.5)
omniauth-oauth2 (>= 1.4.0, < 2.0) omniauth-oauth2 (>= 1.4.0, < 2.0)
omniauth-gitlab (1.0.2) omniauth-gitlab (1.0.3)
omniauth (~> 1.0) omniauth (~> 1.0)
omniauth-oauth2 (~> 1.0) omniauth-oauth2 (~> 1.0)
omniauth-google-oauth2 (0.5.3) omniauth-google-oauth2 (0.5.3)
@ -574,7 +568,7 @@ GEM
omniauth-saml (1.10.0) omniauth-saml (1.10.0)
omniauth (~> 1.3, >= 1.3.2) omniauth (~> 1.3, >= 1.3.2)
ruby-saml (~> 1.7) ruby-saml (~> 1.7)
omniauth-shibboleth (1.2.1) omniauth-shibboleth (1.3.0)
omniauth (>= 1.0.0) omniauth (>= 1.0.0)
omniauth-twitter (1.4.0) omniauth-twitter (1.4.0)
omniauth-oauth (~> 1.1) omniauth-oauth (~> 1.1)
@ -702,16 +696,11 @@ GEM
ffi (>= 0.5.0, < 2) ffi (>= 0.5.0, < 2)
rblineprof (0.3.6) rblineprof (0.3.6)
debugger-ruby_core_source (~> 1.3) debugger-ruby_core_source (~> 1.3)
rbnacl (4.0.2) rdoc (6.0.4)
ffi
rbnacl-libsodium (1.0.11)
rbnacl (>= 3.0.1)
rdoc (4.2.2)
json (~> 1.4)
re2 (1.1.1) re2 (1.1.1)
recaptcha (3.0.0) recaptcha (3.0.0)
json json
recursive-open-struct (1.0.5) recursive-open-struct (1.1.0)
redcarpet (3.4.0) redcarpet (3.4.0)
redis (3.3.5) redis (3.3.5)
redis-actionpack (5.0.2) redis-actionpack (5.0.2)
@ -721,8 +710,8 @@ GEM
redis-activesupport (5.0.4) redis-activesupport (5.0.4)
activesupport (>= 3, < 6) activesupport (>= 3, < 6)
redis-store (>= 1.3, < 2) redis-store (>= 1.3, < 2)
redis-namespace (1.5.2) redis-namespace (1.6.0)
redis (~> 3.0, >= 3.0.4) redis (>= 3.0.4)
redis-rack (2.0.4) redis-rack (2.0.4)
rack (>= 1.5, < 3) rack (>= 1.5, < 3)
redis-store (>= 1.2, < 2) redis-store (>= 1.2, < 2)
@ -752,36 +741,36 @@ GEM
chunky_png chunky_png
rqrcode-rails3 (0.1.7) rqrcode-rails3 (0.1.7)
rqrcode (>= 0.4.2) rqrcode (>= 0.4.2)
rspec (3.6.0) rspec (3.7.0)
rspec-core (~> 3.6.0) rspec-core (~> 3.7.0)
rspec-expectations (~> 3.6.0) rspec-expectations (~> 3.7.0)
rspec-mocks (~> 3.6.0) rspec-mocks (~> 3.7.0)
rspec-core (3.6.0) rspec-core (3.7.1)
rspec-support (~> 3.6.0) rspec-support (~> 3.7.0)
rspec-expectations (3.6.0) rspec-expectations (3.7.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.6.0) rspec-support (~> 3.7.0)
rspec-mocks (3.6.0) rspec-mocks (3.7.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.6.0) rspec-support (~> 3.7.0)
rspec-parameterized (0.4.0) rspec-parameterized (0.4.0)
binding_of_caller binding_of_caller
parser parser
proc_to_ast proc_to_ast
rspec (>= 2.13, < 4) rspec (>= 2.13, < 4)
unparser unparser
rspec-rails (3.6.0) rspec-rails (3.7.2)
actionpack (>= 3.0) actionpack (>= 3.0)
activesupport (>= 3.0) activesupport (>= 3.0)
railties (>= 3.0) railties (>= 3.0)
rspec-core (~> 3.6.0) rspec-core (~> 3.7.0)
rspec-expectations (~> 3.6.0) rspec-expectations (~> 3.7.0)
rspec-mocks (~> 3.6.0) rspec-mocks (~> 3.7.0)
rspec-support (~> 3.6.0) rspec-support (~> 3.7.0)
rspec-retry (0.4.5) rspec-retry (0.4.5)
rspec-core rspec-core
rspec-set (0.1.3) rspec-set (0.1.3)
rspec-support (3.6.0) rspec-support (3.7.1)
rspec_profiling (0.0.5) rspec_profiling (0.0.5)
activerecord activerecord
pg pg
@ -813,7 +802,7 @@ GEM
rubyzip (1.2.1) rubyzip (1.2.1)
rufus-scheduler (3.4.0) rufus-scheduler (3.4.0)
et-orbi (~> 1.0) et-orbi (~> 1.0)
rugged (0.27.1) rugged (0.27.2)
safe_yaml (1.0.4) safe_yaml (1.0.4)
sanitize (4.6.5) sanitize (4.6.5)
crass (~> 1.0.2) crass (~> 1.0.2)
@ -836,15 +825,14 @@ GEM
scss_lint (0.56.0) scss_lint (0.56.0)
rake (>= 0.9, < 13) rake (>= 0.9, < 13)
sass (~> 3.5.3) sass (~> 3.5.3)
securecompare (1.0.0)
seed-fu (2.3.7) seed-fu (2.3.7)
activerecord (>= 3.1) activerecord (>= 3.1)
activesupport (>= 3.1) activesupport (>= 3.1)
select2-rails (3.5.9.3) select2-rails (3.5.9.3)
thor (~> 0.14) thor (~> 0.14)
selenium-webdriver (3.5.0) selenium-webdriver (3.12.0)
childprocess (~> 0.5) childprocess (~> 0.5)
rubyzip (~> 1.0) rubyzip (~> 1.2)
sentry-raven (2.7.2) sentry-raven (2.7.2)
faraday (>= 0.7.6, < 1.0) faraday (>= 0.7.6, < 1.0)
settingslogic (2.0.9) settingslogic (2.0.9)
@ -853,11 +841,11 @@ GEM
rack rack
shoulda-matchers (3.1.2) shoulda-matchers (3.1.2)
activesupport (>= 4.0.0) activesupport (>= 4.0.0)
sidekiq (5.0.5) sidekiq (5.1.3)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0) connection_pool (~> 2.2, >= 2.2.0)
rack-protection (>= 1.5.0) rack-protection (>= 1.5.0)
redis (>= 3.3.4, < 5) redis (>= 3.3.5, < 5)
sidekiq-cron (0.6.0) sidekiq-cron (0.6.0)
rufus-scheduler (>= 3.3.0) rufus-scheduler (>= 3.3.0)
sidekiq (>= 4.2.1) sidekiq (>= 4.2.1)
@ -876,23 +864,11 @@ GEM
simplecov-html (0.10.0) simplecov-html (0.10.0)
slack-notifier (1.5.1) slack-notifier (1.5.1)
slop (3.6.0) slop (3.6.0)
spinach (0.8.10)
colorize
gherkin-ruby (>= 0.3.2)
json
spinach-rails (0.2.1)
capybara (>= 2.0.0)
railties (>= 3)
spinach (>= 0.4)
spinach-rerun-reporter (0.0.2)
spinach (~> 0.8)
spring (2.0.1) spring (2.0.1)
activesupport (>= 4.2) activesupport (>= 4.2)
spring-commands-rspec (1.0.4) spring-commands-rspec (1.0.4)
spring (>= 0.9.1) spring (>= 0.9.1)
spring-commands-spinach (1.1.0) sprockets (3.7.2)
spring (>= 0.9.1)
sprockets (3.7.1)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
rack (> 1, < 3) rack (> 1, < 3)
sprockets-rails (3.2.1) sprockets-rails (3.2.1)
@ -960,7 +936,6 @@ GEM
equalizer (~> 0.0.9) equalizer (~> 0.0.9)
parser (>= 2.3.1.2, < 2.6) parser (>= 2.3.1.2, < 2.6)
procto (~> 0.0.2) procto (~> 0.0.2)
url_safe_base64 (0.2.2)
validates_hostname (1.0.6) validates_hostname (1.0.6)
activerecord (>= 3.0) activerecord (>= 3.0)
activesupport (>= 3.0) activesupport (>= 3.0)
@ -998,13 +973,12 @@ DEPENDENCIES
acts-as-taggable-on (~> 5.0) acts-as-taggable-on (~> 5.0)
addressable (~> 2.5.2) addressable (~> 2.5.2)
akismet (~> 2.0) akismet (~> 2.0)
allocations (~> 1.0)
asana (~> 0.6.0) asana (~> 0.6.0)
asciidoctor (~> 1.5.6) asciidoctor (~> 1.5.6)
asciidoctor-plantuml (= 0.0.8) asciidoctor-plantuml (= 0.0.8)
asset_sync (~> 2.2.0) asset_sync (~> 2.4)
attr_encrypted (~> 3.1.0) attr_encrypted (~> 3.1.0)
awesome_print (~> 1.2.0) awesome_print
babosa (~> 1.0.2) babosa (~> 1.0.2)
base32 (~> 0.3.0) base32 (~> 0.3.0)
batch-loader (~> 1.2.1) batch-loader (~> 1.2.1)
@ -1012,7 +986,6 @@ DEPENDENCIES
benchmark-ips (~> 2.3.0) benchmark-ips (~> 2.3.0)
better_errors (~> 2.1.0) better_errors (~> 2.1.0)
binding_of_caller (~> 0.7.2) binding_of_caller (~> 0.7.2)
bootstrap-sass (~> 3.3.0)
bootstrap_form (~> 2.7.0) bootstrap_form (~> 2.7.0)
brakeman (~> 4.2) brakeman (~> 4.2)
browser (~> 2.2) browser (~> 2.2)
@ -1028,7 +1001,6 @@ DEPENDENCIES
concurrent-ruby (~> 1.0.5) concurrent-ruby (~> 1.0.5)
connection_pool (~> 2.0) connection_pool (~> 2.0)
creole (~> 0.5.0) creole (~> 0.5.0)
d3_rails (~> 3.5.0)
database_cleaner (~> 1.5.0) database_cleaner (~> 1.5.0)
deckar01-task_list (= 2.0.0) deckar01-task_list (= 2.0.0)
default_value_for (~> 3.0.0) default_value_for (~> 3.0.0)
@ -1037,10 +1009,11 @@ DEPENDENCIES
devise-two-factor (~> 3.0.0) devise-two-factor (~> 3.0.0)
diffy (~> 3.1.0) diffy (~> 3.1.0)
doorkeeper (~> 4.3) doorkeeper (~> 4.3)
doorkeeper-openid_connect (~> 1.3) doorkeeper-openid_connect (~> 1.5)
dropzonejs-rails (~> 0.7.1) dropzonejs-rails (~> 0.7.1)
ed25519 (~> 1.2)
email_reply_trimmer (~> 0.1) email_reply_trimmer (~> 0.1)
email_spec (~> 1.6.0) email_spec (~> 2.2.0)
factory_bot_rails (~> 4.8.2) factory_bot_rails (~> 4.8.2)
faraday (~> 0.12) faraday (~> 0.12)
fast_blank fast_blank
@ -1064,31 +1037,34 @@ DEPENDENCIES
gettext (~> 3.2.2) gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3) gettext_i18n_rails_js (~> 1.3)
gitaly-proto (~> 0.99.0) gitaly-proto (~> 0.105.0)
github-linguist (~> 5.3.3) github-linguist (~> 5.3.3)
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-gollum-lib (~> 4.2) gitlab-gollum-lib (~> 4.2)
gitlab-gollum-rugged_adapter (~> 0.4.4) gitlab-gollum-rugged_adapter (~> 0.4.4)
gitlab-markup (~> 1.6.2) gitlab-markup (~> 1.6.4)
gitlab-styles (~> 2.3) gitlab-styles (~> 2.3)
gitlab_omniauth-ldap (~> 2.0.4) gitlab_omniauth-ldap (~> 2.0.4)
gon (~> 6.1.0) gon (~> 6.2)
google-api-client (~> 0.19.8) google-api-client (~> 0.19.8)
google-protobuf (= 3.5.1) google-protobuf (= 3.5.1)
gpgme gpgme
grape (~> 1.0) grape (~> 1.0)
grape-entity (~> 0.7.1) grape-entity (~> 0.7.1)
grape-route-helpers (~> 2.1.0) grape-path-helpers (~> 1.0)
grape_logging (~> 1.7) grape_logging (~> 1.7)
graphiql-rails (~> 1.4.10)
graphql (~> 1.8.0)
grpc (~> 1.11.0) grpc (~> 1.11.0)
haml_lint (~> 0.26.0) haml_lint (~> 0.26.0)
hamlit (~> 2.6.1) hamlit (~> 2.6.1)
hashie-forbidden_attributes hashie-forbidden_attributes
health_check (~> 2.6.0) health_check (~> 2.6.0)
hipchat (~> 1.5.0) hipchat (~> 1.5.0)
html-pipeline (~> 2.7.1) html-pipeline (~> 2.8)
html2text html2text
httparty (~> 0.13.3) httparty (~> 0.13.3)
icalendar
influxdb (~> 0.2) influxdb (~> 0.2)
jira-ruby (~> 1.4) jira-ruby (~> 1.4)
jquery-atwho-rails (~> 1.3.2) jquery-atwho-rails (~> 1.3.2)
@ -1096,7 +1072,7 @@ DEPENDENCIES
jwt (~> 1.5.6) jwt (~> 1.5.6)
kaminari (~> 1.0) kaminari (~> 1.0)
knapsack (~> 1.16) knapsack (~> 1.16)
kubeclient (~> 3.0) kubeclient (~> 3.1.0)
letter_opener_web (~> 1.3.0) letter_opener_web (~> 1.3.0)
license_finder (~> 3.1) license_finder (~> 3.1)
licensee (~> 8.9) licensee (~> 8.9)
@ -1104,17 +1080,18 @@ DEPENDENCIES
loofah (~> 2.2) loofah (~> 2.2)
mail_room (~> 0.9.1) mail_room (~> 0.9.1)
method_source (~> 0.8) method_source (~> 0.8)
mini_magick
minitest (~> 5.7.0) minitest (~> 5.7.0)
mousetrap-rails (~> 1.4.6) mousetrap-rails (~> 1.4.6)
mysql2 (~> 0.4.10) mysql2 (~> 0.4.10)
net-ldap net-ldap
net-ssh (~> 4.2.0) net-ssh (~> 5.0)
nokogiri (~> 1.8.2) nokogiri (~> 1.8.2)
oauth2 (~> 1.4) oauth2 (~> 1.4)
octokit (~> 4.8) octokit (~> 4.9)
omniauth (~> 1.8) omniauth (~> 1.8)
omniauth-auth0 (~> 2.0.0) omniauth-auth0 (~> 2.0.0)
omniauth-authentiq (~> 0.3.1) omniauth-authentiq (~> 0.3.3)
omniauth-azure-oauth2 (~> 0.0.9) omniauth-azure-oauth2 (~> 0.0.9)
omniauth-cas3 (~> 1.1.4) omniauth-cas3 (~> 1.1.4)
omniauth-facebook (~> 4.0.0) omniauth-facebook (~> 4.0.0)
@ -1124,7 +1101,7 @@ DEPENDENCIES
omniauth-kerberos (~> 0.3.0) omniauth-kerberos (~> 0.3.0)
omniauth-oauth2-generic (~> 0.2.2) omniauth-oauth2-generic (~> 0.2.2)
omniauth-saml (~> 1.10) omniauth-saml (~> 1.10)
omniauth-shibboleth (~> 1.2.0) omniauth-shibboleth (~> 1.3.0)
omniauth-twitter (~> 1.4) omniauth-twitter (~> 1.4)
omniauth_crowd (~> 2.2.0) omniauth_crowd (~> 2.2.0)
org-ruby (~> 0.9.12) org-ruby (~> 0.9.12)
@ -1150,21 +1127,19 @@ DEPENDENCIES
rainbow (~> 2.2) rainbow (~> 2.2)
raindrops (~> 0.18) raindrops (~> 0.18)
rblineprof (~> 0.3.6) rblineprof (~> 0.3.6)
rbnacl (~> 4.0) rdoc (~> 6.0)
rbnacl-libsodium
rdoc (~> 4.2)
re2 (~> 1.1.1) re2 (~> 1.1.1)
recaptcha (~> 3.0) recaptcha (~> 3.0)
redcarpet (~> 3.4) redcarpet (~> 3.4)
redis (~> 3.2) redis (~> 3.2)
redis-namespace (~> 1.5.2) redis-namespace (~> 1.6.0)
redis-rails (~> 5.0.2) redis-rails (~> 5.0.2)
request_store (~> 1.3) request_store (~> 1.3)
responders (~> 2.0) responders (~> 2.0)
rouge (~> 3.1) rouge (~> 3.1)
rqrcode-rails3 (~> 0.1.7) rqrcode-rails3 (~> 0.1.7)
rspec-parameterized rspec-parameterized
rspec-rails (~> 3.6.0) rspec-rails (~> 3.7.0)
rspec-retry (~> 0.4.5) rspec-retry (~> 0.4.5)
rspec-set (~> 0.1.3) rspec-set (~> 0.1.3)
rspec_profiling (~> 0.0.5) rspec_profiling (~> 0.0.5)
@ -1172,6 +1147,7 @@ DEPENDENCIES
rubocop-rspec (~> 1.22.1) rubocop-rspec (~> 1.22.1)
ruby-fogbugz (~> 0.2.1) ruby-fogbugz (~> 0.2.1)
ruby-prof (~> 0.17.0) ruby-prof (~> 0.17.0)
ruby-progressbar
ruby_parser (~> 3.8) ruby_parser (~> 3.8)
rufus-scheduler (~> 3.4) rufus-scheduler (~> 3.4)
rugged (~> 0.27) rugged (~> 0.27)
@ -1180,22 +1156,19 @@ DEPENDENCIES
scss_lint (~> 0.56.0) scss_lint (~> 0.56.0)
seed-fu (~> 2.3.7) seed-fu (~> 2.3.7)
select2-rails (~> 3.5.9) select2-rails (~> 3.5.9)
selenium-webdriver (~> 3.5) selenium-webdriver (~> 3.12)
sentry-raven (~> 2.7) sentry-raven (~> 2.7)
settingslogic (~> 2.0.9) settingslogic (~> 2.0.9)
sham_rack (~> 1.3.6) sham_rack (~> 1.3.6)
shoulda-matchers (~> 3.1.2) shoulda-matchers (~> 3.1.2)
sidekiq (~> 5.0) sidekiq (~> 5.1)
sidekiq-cron (~> 0.6.0) sidekiq-cron (~> 0.6.0)
sidekiq-limit_fetch (~> 3.4) sidekiq-limit_fetch (~> 3.4)
simple_po_parser (~> 1.1.2) simple_po_parser (~> 1.1.2)
simplecov (~> 0.14.0) simplecov (~> 0.14.0)
slack-notifier (~> 1.5.1) slack-notifier (~> 1.5.1)
spinach-rails (~> 0.2.1)
spinach-rerun-reporter (~> 0.0.2)
spring (~> 2.0.0) spring (~> 2.0.0)
spring-commands-rspec (~> 1.0.4) spring-commands-rspec (~> 1.0.4)
spring-commands-spinach (~> 1.1.0)
sprockets (~> 3.7.0) sprockets (~> 3.7.0)
sshkey (~> 1.9.0) sshkey (~> 1.9.0)
stackprof (~> 0.2.10) stackprof (~> 0.2.10)
@ -1221,4 +1194,4 @@ DEPENDENCIES
wikicloth (= 0.8.1) wikicloth (= 0.8.1)
BUNDLED WITH BUNDLED WITH
1.16.1 1.16.2

File diff suppressed because it is too large Load diff

1
INSTALLATION_TYPE Normal file
View file

@ -0,0 +1 @@
source

View file

@ -5,8 +5,3 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---
All Documentation content that resides under the doc/ directory of this
repository is licensed under Creative Commons: CC BY-SA 4.0.

View file

@ -15,6 +15,8 @@
- [Between the 1st and the 7th](#between-the-1st-and-the-7th) - [Between the 1st and the 7th](#between-the-1st-and-the-7th)
- [On the 7th](#on-the-7th) - [On the 7th](#on-the-7th)
- [After the 7th](#after-the-7th) - [After the 7th](#after-the-7th)
- [Regressions](#regressions)
- [How to manage a regression](#how-to-manage-a-regression)
- [Release retrospective and kickoff](#release-retrospective-and-kickoff) - [Release retrospective and kickoff](#release-retrospective-and-kickoff)
- [Retrospective](#retrospective) - [Retrospective](#retrospective)
- [Kickoff](#kickoff) - [Kickoff](#kickoff)
@ -168,6 +170,8 @@ the stable branch are:
* Fixes for [regressions](#regressions) * Fixes for [regressions](#regressions)
* Fixes for security issues * Fixes for security issues
* Fixes or improvements to automated QA scenarios
* Documentation updates for changes in the same release
* New or updated translations (as long as they do not touch application code) * New or updated translations (as long as they do not touch application code)
During the feature freeze all merge requests that are meant to go into the During the feature freeze all merge requests that are meant to go into the
@ -184,11 +188,7 @@ next patch release.
If a merge request is to be picked into more than one release it will need one If a merge request is to be picked into more than one release it will need one
`Pick into X.Y` label per release where the merge request should be back-ported `Pick into X.Y` label per release where the merge request should be back-ported
to. to. For example:
For example, if the current patch release is `10.1.1` and a regression fix needs
to be backported down to the `9.5` release, you will need to assign it the
`10.1` milestone and the following labels:
- `Pick into 10.1` - `Pick into 10.1`
- `Pick into 10.0` - `Pick into 10.0`
@ -199,26 +199,9 @@ to be backported down to the `9.5` release, you will need to assign it the
If you think a merge request should go into an RC or patch even though it does not meet these requirements, If you think a merge request should go into an RC or patch even though it does not meet these requirements,
you can ask for an exception to be made. you can ask for an exception to be made.
Go to [Release tasks issue tracker](https://gitlab.com/gitlab-org/release/tasks/issues/new) and create an issue Check [this guide](https://gitlab.com/gitlab-org/release/docs/blob/master/general/exception-request/process.md) about how to open an exception request before opening one.
using the `Exception-request` issue template.
**Do not** set the relevant `Pick into X.Y` label (see above) before request an ## Regressions
exception; this should be done after the exception is approved.
You can find who is who on the [team page](https://about.gitlab.com/team/).
Whether an exception is made is determined by weighing the benefit and urgency of the change
(how important it is to the company that this is released _right now_ instead of in a month)
against the potential negative impact
(things breaking without enough time to comfortably find and fix them before the release on the 22nd).
When in doubt, we err on the side of _not_ cherry-picking.
For example, it is likely that an exception will be made for a trivial 1-5 line performance improvement
(e.g. adding a database index or adding `includes` to a query), but not for a new feature, no matter how relatively small or thoroughly tested.
All MRs which have had exceptions granted must be merged by the 15th.
### Regressions
A regression for a particular monthly release is a bug that exists in that A regression for a particular monthly release is a bug that exists in that
release, but wasn't present in the release before. This includes bugs in release, but wasn't present in the release before. This includes bugs in
@ -236,10 +219,30 @@ month. When we say 'the most recent monthly release', this can refer to either
the version currently running on GitLab.com, or the most recent version the version currently running on GitLab.com, or the most recent version
available in the package repositories. available in the package repositories.
A regression issue should be labeled with the appropriate [subject label](../CONTRIBUTING.md#subject-labels-wiki-container-registry-ldap-api-etc) ### How to manage a regression
and [team label](../CONTRIBUTING.md#team-labels-ci-discussion-edge-platform-etc),
just like any other issue, to help GitLab team members focus on issues that are Regressions are very important, and they should be considered high priority
relevant to [their area of responsibility](https://about.gitlab.com/handbook/engineering/workflow/#choosing-something-to-work-on). issues that should be solved as soon as possible, especially if they affect
users. Despite that, ~regression label itself does not imply when the issue
will be scheduled.
When a regression is found:
1. Create an issue describing the problem in the most detailed way possible
1. If possible, provide links to real examples and how to reproduce the problem
1. Label the issue properly, using the [team label](../CONTRIBUTING.md#team-labels),
the [subject label](../CONTRIBUTING.md#subject-labels)
and any other label that may apply in the specific case
1. Add the ~bug and ~regression labels
1. Notify the respective Engineering Manager to evaluate the Severity of the regression and add a [Severity label](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#bug-severity-labels). The counterpart Product Manager is included to weigh-in on prioritization as needed to set the [Priority label](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#bug-priority-labels).
1. If the regression is either an ~S1, ~S2 or ~S3 severity, label the regression with the current milestone as it should be fixed in the current milestone.
1. If the regression was introduced in an RC of the current release, label with ~Deliverable
1. If the regression was introduced in the previous release, label with ~"Next Patch Release"
1. If the regression is an ~S4 severity, the regression may be scheduled for later milestones at the discretion of Engineering Manager and Product Manager.
When a new issue is found, the fix should start as soon as possible. You can
ping the Engineering Manager or the Product Manager for the relative area to
make them aware of the issue earlier. They will analyze the priority and change
it if needed.
## Release retrospective and kickoff ## Release retrospective and kickoff

View file

@ -2,7 +2,6 @@
[![Build status](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/build.svg)](https://gitlab.com/gitlab-org/gitlab-ce/commits/master) [![Build status](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/build.svg)](https://gitlab.com/gitlab-org/gitlab-ce/commits/master)
[![Overall test coverage](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg)](https://gitlab.com/gitlab-org/gitlab-ce/pipelines) [![Overall test coverage](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg)](https://gitlab.com/gitlab-org/gitlab-ce/pipelines)
[![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.svg)](https://gemnasium.com/gitlabhq/gitlabhq)
[![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq) [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq)
[![Core Infrastructure Initiative Best Practices](https://bestpractices.coreinfrastructure.org/projects/42/badge)](https://bestpractices.coreinfrastructure.org/projects/42) [![Core Infrastructure Initiative Best Practices](https://bestpractices.coreinfrastructure.org/projects/42/badge)](https://bestpractices.coreinfrastructure.org/projects/42)
[![Gitter](https://badges.gitter.im/gitlabhq/gitlabhq.svg)](https://gitter.im/gitlabhq/gitlabhq?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Gitter](https://badges.gitter.im/gitlabhq/gitlabhq.svg)](https://gitter.im/gitlabhq/gitlabhq?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
@ -36,7 +35,7 @@ We're hiring developers, support people, and production engineers all the time,
There are two editions of GitLab: There are two editions of GitLab:
- GitLab Community Edition (CE) is available freely under the MIT Expat license. - GitLab Community Edition (CE) is available freely under the MIT Expat license.
- GitLab Enterprise Edition (EE) includes [extra features](https://about.gitlab.com/products/#compare-options) that are more useful for organizations with more than 100 users. To use EE and get official support please [become a subscriber](https://about.gitlab.com/products/). - GitLab Enterprise Edition (EE) includes [extra features](https://about.gitlab.com/pricing/#compare-options) that are more useful for organizations with more than 100 users. To use EE and get official support please [become a subscriber](https://about.gitlab.com/pricing/).
## Website ## Website
@ -73,6 +72,8 @@ GitLab Community Edition (CE) is available freely under the MIT Expat license.
All third party components incorporated into the GitLab Software are licensed under the original license provided by the owner of the applicable component. All third party components incorporated into the GitLab Software are licensed under the original license provided by the owner of the applicable component.
All Documentation content that resides under the doc/ directory of this repository is licensed under Creative Commons: CC BY-SA 4.0.
## Install a development environment ## Install a development environment
To work on GitLab itself, we recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit). To work on GitLab itself, we recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit).
@ -119,11 +120,15 @@ All documentation can be found on [docs.gitlab.com/ce/](https://docs.gitlab.com/
Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on our website for the many options to get help. Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on our website for the many options to get help.
## Why?
[Read here](https://about.gitlab.com/why/)
## Is it any good? ## Is it any good?
[Yes](https://news.ycombinator.com/item?id=3067434) [Yes](https://news.ycombinator.com/item?id=3067434)
## Is it awesome? ## Is it awesome?
Thanks for [asking this question](https://twitter.com/supersloth/status/489462789384056832) Joshua.
[These people](https://twitter.com/gitlab/likes) seem to like it. [These people](https://twitter.com/gitlab/likes) seem to like it.

View file

@ -1 +1 @@
10.8.7 11.1.8

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,015 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 945 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 919 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -1,4 +1,4 @@
/* eslint-disable no-param-reassign, class-methods-use-this */ /* eslint-disable class-methods-use-this */
import $ from 'jquery'; import $ from 'jquery';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';

View file

@ -26,7 +26,7 @@ export default class AjaxLoadingSpinner {
} }
static toggleLoadingIcon(iconElement) { static toggleLoadingIcon(iconElement) {
const classList = iconElement.classList; const { classList } = iconElement;
classList.toggle(iconElement.dataset.icon); classList.toggle(iconElement.dataset.icon);
classList.toggle('fa-spinner'); classList.toggle('fa-spinner');
classList.toggle('fa-spin'); classList.toggle('fa-spin');

View file

@ -11,6 +11,7 @@ const Api = {
projectPath: '/api/:version/projects/:id', projectPath: '/api/:version/projects/:id',
projectLabelsPath: '/:namespace_path/:project_path/labels', projectLabelsPath: '/:namespace_path/:project_path/labels',
mergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid', mergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid',
mergeRequestsPath: '/api/:version/merge_requests',
mergeRequestChangesPath: '/api/:version/projects/:id/merge_requests/:mrid/changes', mergeRequestChangesPath: '/api/:version/projects/:id/merge_requests/:mrid/changes',
mergeRequestVersionsPath: '/api/:version/projects/:id/merge_requests/:mrid/versions', mergeRequestVersionsPath: '/api/:version/projects/:id/merge_requests/:mrid/versions',
groupLabelsPath: '/groups/:namespace_path/-/labels', groupLabelsPath: '/groups/:namespace_path/-/labels',
@ -21,6 +22,7 @@ const Api = {
issuableTemplatePath: '/:namespace_path/:project_path/templates/:type/:key', issuableTemplatePath: '/:namespace_path/:project_path/templates/:type/:key',
usersPath: '/api/:version/users.json', usersPath: '/api/:version/users.json',
commitPath: '/api/:version/projects/:id/repository/commits', commitPath: '/api/:version/projects/:id/repository/commits',
commitPipelinesPath: '/:project_id/commit/:sha/pipelines',
branchSinglePath: '/api/:version/projects/:id/repository/branches/:branch', branchSinglePath: '/api/:version/projects/:id/repository/branches/:branch',
createBranchPath: '/api/:version/projects/:id/repository/branches', createBranchPath: '/api/:version/projects/:id/repository/branches',
@ -98,12 +100,18 @@ const Api = {
}, },
// Return Merge Request for project // Return Merge Request for project
mergeRequest(projectPath, mergeRequestId) { mergeRequest(projectPath, mergeRequestId, params = {}) {
const url = Api.buildUrl(Api.mergeRequestPath) const url = Api.buildUrl(Api.mergeRequestPath)
.replace(':id', encodeURIComponent(projectPath)) .replace(':id', encodeURIComponent(projectPath))
.replace(':mrid', mergeRequestId); .replace(':mrid', mergeRequestId);
return axios.get(url); return axios.get(url, { params });
},
mergeRequests(params = {}) {
const url = Api.buildUrl(Api.mergeRequestsPath);
return axios.get(url, { params });
}, },
mergeRequestChanges(projectPath, mergeRequestId) { mergeRequestChanges(projectPath, mergeRequestId) {
@ -142,14 +150,15 @@ const Api = {
}, },
// Return group projects list. Filtered by query // Return group projects list. Filtered by query
groupProjects(groupId, query, callback) { groupProjects(groupId, query, options, callback) {
const url = Api.buildUrl(Api.groupProjectsPath).replace(':id', groupId); const url = Api.buildUrl(Api.groupProjectsPath).replace(':id', groupId);
return axios const defaults = {
.get(url, {
params: {
search: query, search: query,
per_page: 20, per_page: 20,
}, };
return axios
.get(url, {
params: Object.assign({}, defaults, options),
}) })
.then(({ data }) => callback(data)); .then(({ data }) => callback(data));
}, },
@ -164,6 +173,19 @@ const Api = {
}); });
}, },
commitPipelines(projectId, sha) {
const encodedProjectId = projectId
.split('/')
.map(fragment => encodeURIComponent(fragment))
.join('/');
const url = Api.buildUrl(Api.commitPipelinesPath)
.replace(':project_id', encodedProjectId)
.replace(':sha', encodeURIComponent(sha));
return axios.get(url);
},
branchSingle(id, branch) { branchSingle(id, branch) {
const url = Api.buildUrl(Api.branchSinglePath) const url = Api.buildUrl(Api.branchSinglePath)
.replace(':id', encodeURIComponent(id)) .replace(':id', encodeURIComponent(id))
@ -222,6 +244,15 @@ const Api = {
}); });
}, },
createBranch(id, { ref, branch }) {
const url = Api.buildUrl(this.createBranchPath).replace(':id', encodeURIComponent(id));
return axios.post(url, {
ref,
branch,
});
},
buildUrl(url) { buildUrl(url) {
let urlRoot = ''; let urlRoot = '';
if (gon.relative_url_root != null) { if (gon.relative_url_root != null) {

View file

@ -1,4 +1,4 @@
/* eslint-disable no-param-reassign, prefer-template, no-var, no-void, consistent-return */ /* eslint-disable no-param-reassign, prefer-template, no-void, consistent-return */
import AccessorUtilities from './lib/utils/accessor'; import AccessorUtilities from './lib/utils/accessor';
@ -31,8 +31,10 @@ export default class Autosave {
// https://github.com/vuejs/vue/issues/2804#issuecomment-216968137 // https://github.com/vuejs/vue/issues/2804#issuecomment-216968137
const event = new Event('change', { bubbles: true, cancelable: false }); const event = new Event('change', { bubbles: true, cancelable: false });
const field = this.field.get(0); const field = this.field.get(0);
if (field) {
field.dispatchEvent(event); field.dispatchEvent(event);
} }
}
save() { save() {
if (!this.field.length) return; if (!this.field.length) return;

View file

@ -11,7 +11,8 @@ import axios from './lib/utils/axios_utils';
const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd'; const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd';
const transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'; const transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd';
const requestAnimationFrame = window.requestAnimationFrame || const requestAnimationFrame =
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame || window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame || window.mozRequestAnimationFrame ||
window.setTimeout; window.setTimeout;
@ -37,21 +38,28 @@ class AwardsHandler {
this.emoji = emoji; this.emoji = emoji;
this.eventListeners = []; this.eventListeners = [];
// If the user shows intent let's pre-build the menu // If the user shows intent let's pre-build the menu
this.registerEventListener('one', $(document), 'mouseenter focus', '.js-add-award', 'mouseenter focus', () => { this.registerEventListener(
'one',
$(document),
'mouseenter focus',
'.js-add-award',
'mouseenter focus',
() => {
const $menu = $('.emoji-menu'); const $menu = $('.emoji-menu');
if ($menu.length === 0) { if ($menu.length === 0) {
requestAnimationFrame(() => { requestAnimationFrame(() => {
this.createEmojiMenu(); this.createEmojiMenu();
}); });
} }
}); },
this.registerEventListener('on', $(document), 'click', '.js-add-award', (e) => { );
this.registerEventListener('on', $(document), 'click', '.js-add-award', e => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
this.showEmojiMenu($(e.currentTarget)); this.showEmojiMenu($(e.currentTarget));
}); });
this.registerEventListener('on', $('html'), 'click', (e) => { this.registerEventListener('on', $('html'), 'click', e => {
const $target = $(e.target); const $target = $(e.target);
if (!$target.closest('.emoji-menu').length) { if (!$target.closest('.emoji-menu').length) {
$('.js-awards-block.current').removeClass('current'); $('.js-awards-block.current').removeClass('current');
@ -61,12 +69,14 @@ class AwardsHandler {
} }
} }
}); });
this.registerEventListener('on', $(document), 'click', '.js-emoji-btn', (e) => { this.registerEventListener('on', $(document), 'click', '.js-emoji-btn', e => {
e.preventDefault(); e.preventDefault();
const $target = $(e.currentTarget); const $target = $(e.currentTarget);
const $glEmojiElement = $target.find('gl-emoji'); const $glEmojiElement = $target.find('gl-emoji');
const $spriteIconElement = $target.find('.icon'); const $spriteIconElement = $target.find('.icon');
const emojiName = ($glEmojiElement.length ? $glEmojiElement : $spriteIconElement).data('name'); const emojiName = ($glEmojiElement.length ? $glEmojiElement : $spriteIconElement).data(
'name',
);
$target.closest('.js-awards-block').addClass('current'); $target.closest('.js-awards-block').addClass('current');
this.addAward(this.getVotesBlock(), this.getAwardUrl(), emojiName); this.addAward(this.getVotesBlock(), this.getAwardUrl(), emojiName);
@ -83,7 +93,10 @@ class AwardsHandler {
showEmojiMenu($addBtn) { showEmojiMenu($addBtn) {
if ($addBtn.hasClass('js-note-emoji')) { if ($addBtn.hasClass('js-note-emoji')) {
$addBtn.closest('.note').find('.js-awards-block').addClass('current'); $addBtn
.closest('.note')
.find('.js-awards-block')
.addClass('current');
} else { } else {
$addBtn.closest('.js-awards-block').addClass('current'); $addBtn.closest('.js-awards-block').addClass('current');
} }
@ -177,8 +190,9 @@ class AwardsHandler {
const remainingCategories = Object.keys(categoryMap).slice(1); const remainingCategories = Object.keys(categoryMap).slice(1);
const allCategoriesAddedPromise = remainingCategories.reduce( const allCategoriesAddedPromise = remainingCategories.reduce(
(promiseChain, categoryNameKey) => (promiseChain, categoryNameKey) =>
promiseChain.then(() => promiseChain.then(
new Promise((resolve) => { () =>
new Promise(resolve => {
const emojisInCategory = categoryMap[categoryNameKey]; const emojisInCategory = categoryMap[categoryNameKey];
const categoryMarkup = this.renderCategory( const categoryMarkup = this.renderCategory(
categoryLabelMap[categoryNameKey], categoryLabelMap[categoryNameKey],
@ -193,14 +207,19 @@ class AwardsHandler {
Promise.resolve(), Promise.resolve(),
); );
allCategoriesAddedPromise.then(() => { allCategoriesAddedPromise
.then(() => {
// Used for tests // Used for tests
// We check for the menu in case it was destroyed in the meantime // We check for the menu in case it was destroyed in the meantime
if (menu) { if (menu) {
menu.dispatchEvent(new CustomEvent('build-emoji-menu-finish')); menu.dispatchEvent(new CustomEvent('build-emoji-menu-finish'));
} }
}).catch((err) => { })
emojiContentElement.insertAdjacentHTML('beforeend', '<p>We encountered an error while adding the remaining categories</p>'); .catch(err => {
emojiContentElement.insertAdjacentHTML(
'beforeend',
'<p>We encountered an error while adding the remaining categories</p>',
);
throw new Error(`Error occurred in addRemainingEmojiMenuCategories: ${err.message}`); throw new Error(`Error occurred in addRemainingEmojiMenuCategories: ${err.message}`);
}); });
} }
@ -211,7 +230,9 @@ class AwardsHandler {
${name} ${name}
</h5> </h5>
<ul class="clearfix emoji-menu-list ${opts.menuListClass || ''}"> <ul class="clearfix emoji-menu-list ${opts.menuListClass || ''}">
${emojiList.map(emojiName => ` ${emojiList
.map(
emojiName => `
<li class="emoji-menu-list-item"> <li class="emoji-menu-list-item">
<button class="emoji-menu-btn text-center js-emoji-btn" type="button"> <button class="emoji-menu-btn text-center js-emoji-btn" type="button">
${this.emoji.glEmojiTag(emojiName, { ${this.emoji.glEmojiTag(emojiName, {
@ -219,7 +240,9 @@ class AwardsHandler {
})} })}
</button> </button>
</li> </li>
`).join('\n')} `,
)
.join('\n')}
</ul> </ul>
`; `;
} }
@ -232,7 +255,7 @@ class AwardsHandler {
top: `${$addBtn.offset().top + $addBtn.outerHeight()}px`, top: `${$addBtn.offset().top + $addBtn.outerHeight()}px`,
}; };
if (position === 'right') { if (position === 'right') {
css.left = `${($addBtn.offset().left - $menu.outerWidth()) + 20}px`; css.left = `${$addBtn.offset().left - $menu.outerWidth() + 20}px`;
$menu.addClass('is-aligned-right'); $menu.addClass('is-aligned-right');
} else { } else {
css.left = `${$addBtn.offset().left}px`; css.left = `${$addBtn.offset().left}px`;
@ -345,7 +368,7 @@ class AwardsHandler {
counter.text(counterNumber - 1); counter.text(counterNumber - 1);
this.removeYouFromUserList($emojiButton); this.removeYouFromUserList($emojiButton);
} else if (emoji === 'thumbsup' || emoji === 'thumbsdown') { } else if (emoji === 'thumbsup' || emoji === 'thumbsdown') {
$emojiButton.tooltip('destroy'); $emojiButton.tooltip('dispose');
counter.text('0'); counter.text('0');
this.removeYouFromUserList($emojiButton); this.removeYouFromUserList($emojiButton);
if ($emojiButton.parents('.note').length) { if ($emojiButton.parents('.note').length) {
@ -358,7 +381,7 @@ class AwardsHandler {
} }
removeEmoji($emojiButton) { removeEmoji($emojiButton) {
$emojiButton.tooltip('destroy'); $emojiButton.tooltip('dispose');
$emojiButton.remove(); $emojiButton.remove();
const $votesBlock = this.getVotesBlock(); const $votesBlock = this.getVotesBlock();
if ($votesBlock.find('.js-emoji-btn').length === 0) { if ($votesBlock.find('.js-emoji-btn').length === 0) {
@ -392,7 +415,7 @@ class AwardsHandler {
.removeAttr('data-title') .removeAttr('data-title')
.removeAttr('data-original-title') .removeAttr('data-original-title')
.attr('title', this.toSentence(authors)) .attr('title', this.toSentence(authors))
.tooltip('fixTitle'); .tooltip('_fixTitle');
} }
addYouToUserList(votesBlock, emoji) { addYouToUserList(votesBlock, emoji) {
@ -405,7 +428,7 @@ class AwardsHandler {
users.unshift('You'); users.unshift('You');
return awardBlock return awardBlock
.attr('title', this.toSentence(users)) .attr('title', this.toSentence(users))
.tooltip('fixTitle'); .tooltip('_fixTitle');
} }
createAwardButtonForVotesBlock(votesBlock, emojiName) { createAwardButtonForVotesBlock(votesBlock, emojiName) {
@ -416,7 +439,10 @@ class AwardsHandler {
</button> </button>
`; `;
const $emojiButton = $(buttonHtml); const $emojiButton = $(buttonHtml);
$emojiButton.insertBefore(votesBlock.find('.js-award-holder')).find('.emoji-icon').data('name', emojiName); $emojiButton
.insertBefore(votesBlock.find('.js-award-holder'))
.find('.emoji-icon')
.data('name', emojiName);
this.animateEmoji($emojiButton); this.animateEmoji($emojiButton);
$('.award-control').tooltip(); $('.award-control').tooltip();
votesBlock.removeClass('current'); votesBlock.removeClass('current');
@ -426,7 +452,7 @@ class AwardsHandler {
const className = 'pulse animated once short'; const className = 'pulse animated once short';
$emoji.addClass(className); $emoji.addClass(className);
this.registerEventListener('on', $emoji, animationEndEventString, (e) => { this.registerEventListener('on', $emoji, animationEndEventString, e => {
$(e.currentTarget).removeClass(className); $(e.currentTarget).removeClass(className);
}); });
} }
@ -444,7 +470,8 @@ class AwardsHandler {
if (this.isUserAuthored($emojiButton)) { if (this.isUserAuthored($emojiButton)) {
this.userAuthored($emojiButton); this.userAuthored($emojiButton);
} else { } else {
axios.post(awardUrl, { axios
.post(awardUrl, {
name: emoji, name: emoji,
}) })
.then(({ data }) => { .then(({ data }) => {
@ -486,26 +513,33 @@ class AwardsHandler {
} }
getFrequentlyUsedEmojis() { getFrequentlyUsedEmojis() {
return this.frequentlyUsedEmojis || (() => { return (
const frequentlyUsedEmojis = _.uniq((Cookies.get('frequently_used_emojis') || '').split(',')); this.frequentlyUsedEmojis ||
this.frequentlyUsedEmojis = frequentlyUsedEmojis.filter( (() => {
inputName => this.emoji.isEmojiNameValid(inputName), const frequentlyUsedEmojis = _.uniq(
(Cookies.get('frequently_used_emojis') || '').split(','),
);
this.frequentlyUsedEmojis = frequentlyUsedEmojis.filter(inputName =>
this.emoji.isEmojiNameValid(inputName),
); );
return this.frequentlyUsedEmojis; return this.frequentlyUsedEmojis;
})(); })()
);
} }
setupSearch() { setupSearch() {
const $search = $('.js-emoji-menu-search'); const $search = $('.js-emoji-menu-search');
this.registerEventListener('on', $search, 'input', (e) => { this.registerEventListener('on', $search, 'input', e => {
const term = $(e.target).val().trim(); const term = $(e.target)
.val()
.trim();
this.searchEmojis(term); this.searchEmojis(term);
}); });
const $menu = $('.emoji-menu'); const $menu = $('.emoji-menu');
this.registerEventListener('on', $menu, transitionEndEventString, (e) => { this.registerEventListener('on', $menu, transitionEndEventString, e => {
if (e.target === e.currentTarget) { if (e.target === e.currentTarget) {
// Clear the search // Clear the search
this.searchEmojis(''); this.searchEmojis('');
@ -523,19 +557,26 @@ class AwardsHandler {
// Generate a search result block // Generate a search result block
const h5 = $('<h5 class="emoji-search-title"/>').text('Search results'); const h5 = $('<h5 class="emoji-search-title"/>').text('Search results');
const foundEmojis = this.findMatchingEmojiElements(term).show(); const foundEmojis = this.findMatchingEmojiElements(term).show();
const ul = $('<ul>').addClass('emoji-menu-list emoji-menu-search').append(foundEmojis); const ul = $('<ul>')
.addClass('emoji-menu-list emoji-menu-search')
.append(foundEmojis);
$('.emoji-menu-content ul, .emoji-menu-content h5').hide(); $('.emoji-menu-content ul, .emoji-menu-content h5').hide();
$('.emoji-menu-content').append(h5).append(ul); $('.emoji-menu-content')
.append(h5)
.append(ul);
} else { } else {
$('.emoji-menu-content').children().show(); $('.emoji-menu-content')
.children()
.show();
} }
} }
findMatchingEmojiElements(query) { findMatchingEmojiElements(query) {
const emojiMatches = this.emoji.filterEmojiNamesByAlias(query); const emojiMatches = this.emoji.filterEmojiNamesByAlias(query);
const $emojiElements = $('.emoji-menu-list:not(.frequent-emojis) [data-name]'); const $emojiElements = $('.emoji-menu-list:not(.frequent-emojis) [data-name]');
const $matchingElements = $emojiElements const $matchingElements = $emojiElements.filter(
.filter((i, elm) => emojiMatches.indexOf(elm.dataset.name) >= 0); (i, elm) => emojiMatches.indexOf(elm.dataset.name) >= 0,
);
return $matchingElements.closest('li').clone(); return $matchingElements.closest('li').clone();
} }
@ -550,16 +591,13 @@ class AwardsHandler {
$emojiMenu.addClass(IS_RENDERED); $emojiMenu.addClass(IS_RENDERED);
// enqueues animation as a microtask, so it begins ASAP once IS_RENDERED added // enqueues animation as a microtask, so it begins ASAP once IS_RENDERED added
return Promise.resolve() return Promise.resolve().then(() => $emojiMenu.addClass(IS_VISIBLE));
.then(() => $emojiMenu.addClass(IS_VISIBLE));
} }
hideMenuElement($emojiMenu) { hideMenuElement($emojiMenu) {
$emojiMenu.on(transitionEndEventString, (e) => { $emojiMenu.on(transitionEndEventString, e => {
if (e.currentTarget === e.target) { if (e.currentTarget === e.target) {
$emojiMenu $emojiMenu.removeClass(IS_RENDERED).off(transitionEndEventString);
.removeClass(IS_RENDERED)
.off(transitionEndEventString);
} }
}); });
@ -567,7 +605,7 @@ class AwardsHandler {
} }
destroy() { destroy() {
this.eventListeners.forEach((entry) => { this.eventListeners.forEach(entry => {
entry.element.off.call(entry.element, ...entry.args); entry.element.off.call(entry.element, ...entry.args);
}); });
$('.emoji-menu').remove(); $('.emoji-menu').remove();
@ -577,8 +615,9 @@ class AwardsHandler {
let awardsHandlerPromise = null; let awardsHandlerPromise = null;
export default function loadAwardsHandler(reload = false) { export default function loadAwardsHandler(reload = false) {
if (!awardsHandlerPromise || reload) { if (!awardsHandlerPromise || reload) {
awardsHandlerPromise = import(/* webpackChunkName: 'emoji' */ './emoji') awardsHandlerPromise = import(/* webpackChunkName: 'emoji' */ './emoji').then(
.then(Emoji => new AwardsHandler(Emoji)); Emoji => new AwardsHandler(Emoji),
);
} }
return awardsHandlerPromise; return awardsHandlerPromise;
} }

View file

@ -72,11 +72,11 @@ export default {
rel="noopener noreferrer" rel="noopener noreferrer"
> >
<img <img
class="project-badge"
:src="imageUrlWithRetries" :src="imageUrlWithRetries"
class="project-badge"
aria-hidden="true"
@load="onLoad" @load="onLoad"
@error="onError" @error="onError"
aria-hidden="true"
/> />
</a> </a>
@ -89,32 +89,32 @@ export default {
v-show="hasError" v-show="hasError"
class="btn-group" class="btn-group"
> >
<div class="btn btn-default btn-xs disabled"> <div class="btn btn-default btn-sm disabled">
<icon <icon
:size="16"
class="prepend-left-8 append-right-8" class="prepend-left-8 append-right-8"
name="doc_image" name="doc_image"
:size="16"
aria-hidden="true" aria-hidden="true"
/> />
</div> </div>
<div <div
class="btn btn-default btn-xs disabled" class="btn btn-default btn-sm disabled"
> >
<span class="prepend-left-8 append-right-8">{{ s__('Badges|No badge image') }}</span> <span class="prepend-left-8 append-right-8">{{ s__('Badges|No badge image') }}</span>
</div> </div>
</div> </div>
<button <button
v-show="hasError"
class="btn btn-transparent btn-xs text-primary"
type="button"
v-tooltip v-tooltip
v-show="hasError"
:title="s__('Badges|Reload badge image')" :title="s__('Badges|Reload badge image')"
class="btn btn-transparent btn-sm text-primary"
type="button"
@click="reloadImage" @click="reloadImage"
> >
<icon <icon
name="retry"
:size="16" :size="16"
name="retry"
/> />
</button> </button>
</div> </div>

View file

@ -153,14 +153,14 @@ export default {
<label for="badge-link-url">{{ s__('Badges|Link') }}</label> <label for="badge-link-url">{{ s__('Badges|Link') }}</label>
<input <input
id="badge-link-url" id="badge-link-url"
type="text"
class="form-control"
v-model="linkUrl" v-model="linkUrl"
:placeholder="$options.badgeLinkUrlPlaceholder" :placeholder="$options.badgeLinkUrlPlaceholder"
type="text"
class="form-control"
@input="debouncedPreview" @input="debouncedPreview"
/> />
<span <span
class="help-block" class="form-text text-muted"
v-html="helpText" v-html="helpText"
></span> ></span>
</div> </div>
@ -169,14 +169,14 @@ export default {
<label for="badge-image-url">{{ s__('Badges|Badge image URL') }}</label> <label for="badge-image-url">{{ s__('Badges|Badge image URL') }}</label>
<input <input
id="badge-image-url" id="badge-image-url"
type="text"
class="form-control"
v-model="imageUrl" v-model="imageUrl"
:placeholder="$options.badgeImageUrlPlaceholder" :placeholder="$options.badgeImageUrlPlaceholder"
type="text"
class="form-control"
@input="debouncedPreview" @input="debouncedPreview"
/> />
<span <span
class="help-block" class="form-text text-muted"
v-html="helpText" v-html="helpText"
></span> ></span>
</div> </div>
@ -184,8 +184,8 @@ export default {
<div class="form-group"> <div class="form-group">
<label for="badge-preview">{{ s__('Badges|Badge image preview') }}</label> <label for="badge-preview">{{ s__('Badges|Badge image preview') }}</label>
<badge <badge
id="badge-preview"
v-show="renderedBadge && !isRendering" v-show="renderedBadge && !isRendering"
id="badge-preview"
:image-url="renderedImageUrl" :image-url="renderedImageUrl"
:link-url="renderedLinkUrl" :link-url="renderedLinkUrl"
/> />
@ -202,16 +202,16 @@ export default {
<div class="row-content-block"> <div class="row-content-block">
<loading-button <loading-button
type="submit"
container-class="btn btn-success"
:disabled="!canSubmit" :disabled="!canSubmit"
:loading="isSaving" :loading="isSaving"
:label="submitButtonLabel" :label="submitButtonLabel"
type="submit"
container-class="btn btn-success"
/> />
<button <button
v-if="isEditing"
class="btn btn-cancel" class="btn btn-cancel"
type="button" type="button"
v-if="isEditing"
@click="onCancel" @click="onCancel"
>{{ __('Cancel') }}</button> >{{ __('Cancel') }}</button>
</div> </div>

View file

@ -23,8 +23,8 @@ export default {
</script> </script>
<template> <template>
<div class="panel panel-default"> <div class="card">
<div class="panel-heading"> <div class="card-header">
{{ s__('Badges|Your badges') }} {{ s__('Badges|Your badges') }}
<span <span
v-show="!isLoading" v-show="!isLoading"
@ -33,19 +33,19 @@ export default {
</div> </div>
<loading-icon <loading-icon
v-show="isLoading" v-show="isLoading"
class="panel-body" class="card-body"
size="2" size="2"
/> />
<div <div
v-if="hasNoBadges" v-if="hasNoBadges"
class="panel-body" class="card-body"
> >
<span v-if="isGroupBadge">{{ s__('Badges|This group has no badges') }}</span> <span v-if="isGroupBadge">{{ s__('Badges|This group has no badges') }}</span>
<span v-else>{{ s__('Badges|This project has no badges') }}</span> <span v-else>{{ s__('Badges|This project has no badges') }}</span>
</div> </div>
<div <div
v-else v-else
class="panel-body" class="card-body"
> >
<badge-list-row <badge-list-row
v-for="badge in badges" v-for="badge in badges"

View file

@ -41,9 +41,9 @@ export default {
<template> <template>
<div class="gl-responsive-table-row-layout gl-responsive-table-row"> <div class="gl-responsive-table-row-layout gl-responsive-table-row">
<badge <badge
class="table-section section-30"
:image-url="badge.renderedImageUrl" :image-url="badge.renderedImageUrl"
:link-url="badge.renderedLinkUrl" :link-url="badge.renderedLinkUrl"
class="table-section section-30"
/> />
<span class="table-section section-50 str-truncated">{{ badge.linkUrl }}</span> <span class="table-section section-50 str-truncated">{{ badge.linkUrl }}</span>
<div class="table-section section-10"> <div class="table-section section-10">
@ -54,29 +54,29 @@ export default {
v-if="canEditBadge" v-if="canEditBadge"
class="table-action-buttons"> class="table-action-buttons">
<button <button
:disabled="badge.isDeleting"
class="btn btn-default append-right-8" class="btn btn-default append-right-8"
type="button" type="button"
:disabled="badge.isDeleting"
@click="editBadge(badge)" @click="editBadge(badge)"
> >
<icon <icon
name="pencil"
:size="16" :size="16"
:aria-label="__('Edit')" :aria-label="__('Edit')"
name="pencil"
/> />
</button> </button>
<button <button
:disabled="badge.isDeleting"
class="btn btn-danger" class="btn btn-danger"
type="button" type="button"
data-toggle="modal" data-toggle="modal"
data-target="#delete-badge-modal" data-target="#delete-badge-modal"
:disabled="badge.isDeleting"
@click="updateBadgeInModal(badge)" @click="updateBadgeInModal(badge)"
> >
<icon <icon
name="remove"
:size="16" :size="16"
:aria-label="__('Delete')" :aria-label="__('Delete')"
name="remove"
/> />
</button> </button>
<loading-icon <loading-icon

View file

@ -44,8 +44,8 @@ export default {
<gl-modal <gl-modal
id="delete-badge-modal" id="delete-badge-modal"
:header-title-text="s__('Badges|Delete badge?')" :header-title-text="s__('Badges|Delete badge?')"
footer-primary-button-variant="danger"
:footer-primary-button-text="s__('Badges|Delete badge')" :footer-primary-button-text="s__('Badges|Delete badge')"
footer-primary-button-variant="danger"
@submit="onSubmitModal"> @submit="onSubmitModal">
<div class="well"> <div class="well">
<badge <badge

View file

@ -8,10 +8,10 @@ function showTooltip(target, title) {
if (!$target.data('hideTooltip')) { if (!$target.data('hideTooltip')) {
$target $target
.attr('title', title) .attr('title', title)
.tooltip('fixTitle') .tooltip('_fixTitle')
.tooltip('show') .tooltip('show')
.attr('title', originalTitle) .attr('title', originalTitle)
.tooltip('fixTitle'); .tooltip('_fixTitle');
} }
} }
@ -52,7 +52,7 @@ export default function initCopyToClipboard() {
* data types to the intended values. * data types to the intended values.
*/ */
$(document).on('copy', 'body > textarea[readonly]', (e) => { $(document).on('copy', 'body > textarea[readonly]', (e) => {
const clipboardData = e.originalEvent.clipboardData; const { clipboardData } = e.originalEvent;
if (!clipboardData) return; if (!clipboardData) return;
const text = e.target.value; const text = e.target.value;

View file

@ -1,4 +1,4 @@
/* eslint-disable class-methods-use-this, object-shorthand, no-unused-vars, no-use-before-define, no-new, max-len, no-restricted-syntax, guard-for-in, no-continue */ /* eslint-disable object-shorthand, no-unused-vars, no-use-before-define, max-len, no-restricted-syntax, guard-for-in, no-continue */
import $ from 'jquery'; import $ from 'jquery';
import _ from 'underscore'; import _ from 'underscore';
@ -119,7 +119,7 @@ const gfmRules = {
return el.outerHTML; return el.outerHTML;
}, },
'dl'(el, text) { 'dl'(el, text) {
let lines = text.trim().split('\n'); let lines = text.replace(/\n\n/g, '\n').trim().split('\n');
// Add two spaces to the front of subsequent list items lines, // Add two spaces to the front of subsequent list items lines,
// or leave the line entirely blank. // or leave the line entirely blank.
lines = lines.map((l) => { lines = lines.map((l) => {
@ -129,9 +129,13 @@ const gfmRules = {
return ` ${line}`; return ` ${line}`;
}); });
return `<dl>\n${lines.join('\n')}\n</dl>`; return `<dl>\n${lines.join('\n')}\n</dl>\n`;
}, },
'sub, dt, dd, kbd, q, samp, var, ruby, rt, rp, abbr, summary, details'(el, text) { 'dt, dd, summary, details'(el, text) {
const tag = el.nodeName.toLowerCase();
return `<${tag}>${text}</${tag}>\n`;
},
'sup, sub, kbd, q, samp, var, ruby, rt, rp, abbr'(el, text) {
const tag = el.nodeName.toLowerCase(); const tag = el.nodeName.toLowerCase();
return `<${tag}>${text}</${tag}>`; return `<${tag}>${text}</${tag}>`;
}, },
@ -215,22 +219,22 @@ const gfmRules = {
return text.replace(/^- /mg, '1. '); return text.replace(/^- /mg, '1. ');
}, },
'h1'(el, text) { 'h1'(el, text) {
return `# ${text.trim()}`; return `# ${text.trim()}\n`;
}, },
'h2'(el, text) { 'h2'(el, text) {
return `## ${text.trim()}`; return `## ${text.trim()}\n`;
}, },
'h3'(el, text) { 'h3'(el, text) {
return `### ${text.trim()}`; return `### ${text.trim()}\n`;
}, },
'h4'(el, text) { 'h4'(el, text) {
return `#### ${text.trim()}`; return `#### ${text.trim()}\n`;
}, },
'h5'(el, text) { 'h5'(el, text) {
return `##### ${text.trim()}`; return `##### ${text.trim()}\n`;
}, },
'h6'(el, text) { 'h6'(el, text) {
return `###### ${text.trim()}`; return `###### ${text.trim()}\n`;
}, },
'strong'(el, text) { 'strong'(el, text) {
return `**${text}**`; return `**${text}**`;
@ -241,11 +245,13 @@ const gfmRules = {
'del'(el, text) { 'del'(el, text) {
return `~~${text}~~`; return `~~${text}~~`;
}, },
'sup'(el, text) {
return `^${text}`;
},
'hr'(el) { 'hr'(el) {
return '-----'; // extra leading \n is to ensure that there is a blank line between
// a list followed by an hr, otherwise this breaks old redcarpet rendering
return '\n-----\n';
},
'p'(el, text) {
return `${text.trim()}\n`;
}, },
'table'(el) { 'table'(el) {
const theadEl = el.querySelector('thead'); const theadEl = el.querySelector('thead');
@ -263,7 +269,9 @@ const gfmRules = {
let before = ''; let before = '';
let after = ''; let after = '';
switch (cell.style.textAlign) { const alignment = cell.align || cell.style.textAlign;
switch (alignment) {
case 'center': case 'center':
before = ':'; before = ':';
after = ':'; after = ':';
@ -313,7 +321,7 @@ export class CopyAsGFM {
} }
static copyAsGFM(e, transformer) { static copyAsGFM(e, transformer) {
const clipboardData = e.originalEvent.clipboardData; const { clipboardData } = e.originalEvent;
if (!clipboardData) return; if (!clipboardData) return;
const documentFragment = getSelectedFragment(); const documentFragment = getSelectedFragment();
@ -330,7 +338,7 @@ export class CopyAsGFM {
} }
static pasteGFM(e) { static pasteGFM(e) {
const clipboardData = e.originalEvent.clipboardData; const { clipboardData } = e.originalEvent;
if (!clipboardData) return; if (!clipboardData) return;
const text = clipboardData.getData('text/plain'); const text = clipboardData.getData('text/plain');

View file

@ -69,7 +69,7 @@ $(document).on('keyup.quick_submit', '.js-quick-submit input[type=submit], .js-q
$this.tooltip({ $this.tooltip({
container: 'body', container: 'body',
html: 'true', html: 'true',
placement: 'auto top', placement: 'top',
title, title,
trigger: 'manual', trigger: 'manual',
}); });

View file

@ -42,9 +42,9 @@ $.fn.requiresInput = function requiresInput() {
function hideOrShowHelpBlock(form) { function hideOrShowHelpBlock(form) {
const selected = $('.js-select-namespace option:selected'); const selected = $('.js-select-namespace option:selected');
if (selected.length && selected.data('optionsParent') === 'groups') { if (selected.length && selected.data('optionsParent') === 'groups') {
form.find('.help-block').hide(); form.find('.form-text.text-muted').hide();
} else if (selected.length) { } else if (selected.length) {
form.find('.help-block').show(); form.find('.form-text.text-muted').show();
} }
} }

View file

@ -2,9 +2,9 @@ import sqljs from 'sql.js';
import { template as _template } from 'underscore'; import { template as _template } from 'underscore';
const PREVIEW_TEMPLATE = _template(` const PREVIEW_TEMPLATE = _template(`
<div class="panel panel-default"> <div class="card">
<div class="panel-heading"><%- name %></div> <div class="card-header"><%- name %></div>
<div class="panel-body"> <div class="card-body">
<img class="img-thumbnail" src="data:image/png;base64,<%- image %>"/> <img class="img-thumbnail" src="data:image/png;base64,<%- image %>"/>
</div> </div>
</div> </div>
@ -84,7 +84,7 @@ class BalsamiqViewer {
renderTemplate(preview) { renderTemplate(preview) {
const resource = this.getResource(preview.resourceID); const resource = this.getResource(preview.resourceID);
const name = BalsamiqViewer.parseTitle(resource); const name = BalsamiqViewer.parseTitle(resource);
const image = preview.image; const { image } = preview;
const template = PREVIEW_TEMPLATE({ const template = PREVIEW_TEMPLATE({
name, name,

View file

@ -12,7 +12,7 @@ export default function loadBalsamiqFile() {
if (!(viewer instanceof Element)) return; if (!(viewer instanceof Element)) return;
const endpoint = viewer.dataset.endpoint; const { endpoint } = viewer.dataset;
const balsamiqViewer = new BalsamiqViewer(viewer); const balsamiqViewer = new BalsamiqViewer(viewer);
balsamiqViewer.loadFile(endpoint).catch(onError); balsamiqViewer.loadFile(endpoint).catch(onError);

View file

@ -1,4 +1,3 @@
/* eslint-disable no-new */
import Vue from 'vue'; import Vue from 'vue';
import pdfLab from '../../pdf/index.vue'; import pdfLab from '../../pdf/index.vue';

View file

@ -44,7 +44,7 @@ export default class SketchLoader {
previewLink.href = previewUrl; previewLink.href = previewUrl;
previewLink.target = '_blank'; previewLink.target = '_blank';
previewImage.src = previewUrl; previewImage.src = previewUrl;
previewImage.className = 'img-responsive'; previewImage.className = 'img-fluid';
previewLink.appendChild(previewImage); previewLink.appendChild(previewImage);
this.container.appendChild(previewLink); this.container.appendChild(previewLink);

View file

@ -5,7 +5,7 @@ export default () => {
[].slice.call(document.querySelectorAll('.js-material-changer')).forEach((el) => { [].slice.call(document.querySelectorAll('.js-material-changer')).forEach((el) => {
el.addEventListener('click', (e) => { el.addEventListener('click', (e) => {
const target = e.target; const { target } = e;
e.preventDefault(); e.preventDefault();

View file

@ -70,7 +70,7 @@ export default class BlobViewer {
const initialViewer = this.$fileHolder[0].querySelector('.blob-viewer:not(.hidden)'); const initialViewer = this.$fileHolder[0].querySelector('.blob-viewer:not(.hidden)');
let initialViewerName = initialViewer.getAttribute('data-type'); let initialViewerName = initialViewer.getAttribute('data-type');
if (this.switcher && location.hash.indexOf('#L') === 0) { if (this.switcher && window.location.hash.indexOf('#L') === 0) {
initialViewerName = 'simple'; initialViewerName = 'simple';
} }
@ -116,7 +116,7 @@ export default class BlobViewer {
this.copySourceBtn.classList.add('disabled'); this.copySourceBtn.classList.add('disabled');
} }
$(this.copySourceBtn).tooltip('fixTitle'); $(this.copySourceBtn).tooltip('_fixTitle');
} }
switchToViewer(name) { switchToViewer(name) {

View file

@ -1,5 +1,4 @@
/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, quotes, vars-on-top, no-unused-vars, no-new, max-len */ /* eslint-disable no-new */
/* global EditBlob */
import $ from 'jquery'; import $ from 'jquery';
import NewCommitForm from '../new_commit_form'; import NewCommitForm from '../new_commit_form';

View file

@ -1,7 +1,6 @@
/* eslint-disable comma-dangle, space-before-function-paren, one-var */ /* eslint-disable comma-dangle */
import $ from 'jquery'; import Sortable from 'sortablejs';
import Sortable from 'vendor/Sortable';
import Vue from 'vue'; import Vue from 'vue';
import AccessorUtilities from '../../lib/utils/accessor'; import AccessorUtilities from '../../lib/utils/accessor';
import boardList from './board_list.vue'; import boardList from './board_list.vue';
@ -14,17 +13,28 @@ window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {}; window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.Board = Vue.extend({ gl.issueBoards.Board = Vue.extend({
template: '#js-board-template',
components: { components: {
boardList, boardList,
'board-delete': gl.issueBoards.BoardDelete, 'board-delete': gl.issueBoards.BoardDelete,
BoardBlankState, BoardBlankState,
}, },
props: { props: {
list: Object, list: {
disabled: Boolean, type: Object,
issueLinkBase: String, default: () => ({}),
rootPath: String, },
disabled: {
type: Boolean,
required: true,
},
issueLinkBase: {
type: String,
required: true,
},
rootPath: {
type: String,
required: true,
},
boardId: { boardId: {
type: String, type: String,
required: true, required: true,
@ -46,55 +56,7 @@ gl.issueBoards.Board = Vue.extend({
}); });
}, },
deep: true, deep: true,
},
detailIssue: {
handler () {
if (!Object.keys(this.detailIssue.issue).length) return;
const issue = this.list.findIssue(this.detailIssue.issue.id);
if (issue) {
const offsetLeft = this.$el.offsetLeft;
const boardsList = document.querySelectorAll('.boards-list')[0];
const left = boardsList.scrollLeft - offsetLeft;
let right = (offsetLeft + this.$el.offsetWidth);
if (window.innerWidth > 768 && boardsList.classList.contains('is-compact')) {
// -290 here because width of boardsList is animating so therefore
// getting the width here is incorrect
// 290 is the width of the sidebar
right -= (boardsList.offsetWidth - 290);
} else {
right -= boardsList.offsetWidth;
} }
if (right - boardsList.scrollLeft > 0) {
$(boardsList).animate({
scrollLeft: right
}, this.sortableOptions.animation);
} else if (left > 0) {
$(boardsList).animate({
scrollLeft: offsetLeft
}, this.sortableOptions.animation);
}
}
},
deep: true
}
},
methods: {
showNewIssueForm() {
this.$refs['board-list'].showIssueForm = !this.$refs['board-list'].showIssueForm;
},
toggleExpanded(e) {
if (this.list.isExpandable && !e.target.classList.contains('js-no-trigger-collapse')) {
this.list.isExpanded = !this.list.isExpanded;
if (AccessorUtilities.isLocalStorageAccessSafe()) {
localStorage.setItem(`boards.${this.boardId}.${this.list.type}.expanded`, this.list.isExpanded);
}
}
},
}, },
mounted () { mounted () {
this.sortableOptions = gl.issueBoards.getBoardSortableDefaultOptions({ this.sortableOptions = gl.issueBoards.getBoardSortableDefaultOptions({
@ -125,4 +87,19 @@ gl.issueBoards.Board = Vue.extend({
this.list.isExpanded = !isCollapsed; this.list.isExpanded = !isCollapsed;
} }
}, },
methods: {
showNewIssueForm() {
this.$refs['board-list'].showIssueForm = !this.$refs['board-list'].showIssueForm;
},
toggleExpanded(e) {
if (this.list.isExpandable && !e.target.classList.contains('js-no-trigger-collapse')) {
this.list.isExpanded = !this.list.isExpanded;
if (AccessorUtilities.isLocalStorageAccessSafe()) {
localStorage.setItem(`boards.${this.boardId}.${this.list.type}.expanded`, this.list.isExpanded);
}
}
},
},
template: '#js-board-template',
}); });

View file

@ -72,8 +72,8 @@ export default {
:key="index" :key="index"
> >
<span <span
class="label-color" :style="{ backgroundColor: label.color }"
:style="{ backgroundColor: label.color }"> class="label-color">
</span> </span>
{{ label.title }} {{ label.title }}
</li> </li>

View file

@ -1,14 +1,14 @@
<script> <script>
/* eslint-disable vue/require-default-prop */ /* eslint-disable vue/require-default-prop */
import './issue_card_inner'; import IssueCardInner from './issue_card_inner.vue';
import eventHub from '../eventhub'; import eventHub from '../eventhub';
const Store = gl.issueBoards.BoardsStore; const Store = gl.issueBoards.BoardsStore;
export default { export default {
name: 'BoardsIssueCard', name: 'BoardsIssueCard',
components: { components: {
'issue-card-inner': gl.issueBoards.IssueCardInner, IssueCardInner,
}, },
props: { props: {
list: { list: {
@ -72,12 +72,11 @@ export default {
} }
}, },
}, },
}; };
</script> </script>
<template> <template>
<li <li
class="card"
:class="{ :class="{
'user-can-drag': !disabled && issue.id, 'user-can-drag': !disabled && issue.id,
'is-disabled': disabled || !issue.id, 'is-disabled': disabled || !issue.id,
@ -85,6 +84,7 @@ export default {
}" }"
:index="index" :index="index"
:data-issue-id="issue.id" :data-issue-id="issue.id"
class="board-card"
@mousedown="mouseDown" @mousedown="mouseDown"
@mousemove="mouseMove" @mousemove="mouseMove"
@mouseup="showIssue($event)"> @mouseup="showIssue($event)">

View file

@ -1,4 +1,4 @@
/* eslint-disable comma-dangle, space-before-function-paren, no-alert */ /* eslint-disable comma-dangle, no-alert */
import $ from 'jquery'; import $ from 'jquery';
import Vue from 'vue'; import Vue from 'vue';
@ -8,13 +8,16 @@ window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.BoardDelete = Vue.extend({ gl.issueBoards.BoardDelete = Vue.extend({
props: { props: {
list: Object list: {
type: Object,
default: () => ({}),
},
}, },
methods: { methods: {
deleteBoard () { deleteBoard () {
$(this.$el).tooltip('hide'); $(this.$el).tooltip('hide');
if (confirm('Are you sure you want to delete this list?')) { if (window.confirm('Are you sure you want to delete this list?')) {
this.list.destroy(); this.list.destroy();
} }
} }

View file

@ -1,5 +1,5 @@
<script> <script>
import Sortable from 'vendor/Sortable'; import Sortable from 'sortablejs';
import boardNewIssue from './board_new_issue.vue'; import boardNewIssue from './board_new_issue.vue';
import boardCard from './board_card.vue'; import boardCard from './board_card.vue';
import eventHub from '../eventhub'; import eventHub from '../eventhub';
@ -87,10 +87,46 @@ export default {
mounted() { mounted() {
const options = gl.issueBoards.getBoardSortableDefaultOptions({ const options = gl.issueBoards.getBoardSortableDefaultOptions({
scroll: true, scroll: true,
group: 'issues',
disabled: this.disabled, disabled: this.disabled,
filter: '.board-list-count, .is-disabled', filter: '.board-list-count, .is-disabled',
dataIdAttr: 'data-issue-id', dataIdAttr: 'data-issue-id',
group: {
name: 'issues',
/**
* Dynamically determine between which containers
* items can be moved or copied as
* Assignee lists (EE feature) require this behavior
*/
pull: (to, from, dragEl, e) => {
// As per Sortable's docs, `to` should provide
// reference to exact sortable container on which
// we're trying to drag element, but either it is
// a library's bug or our markup structure is too complex
// that `to` never points to correct container
// See https://github.com/RubaXa/Sortable/issues/1037
//
// So we use `e.target` which is always accurate about
// which element we're currently dragging our card upon
// So from there, we can get reference to actual container
// and thus the container type to enable Copy or Move
if (e.target) {
const containerEl = e.target.closest('.js-board-list') || e.target.querySelector('.js-board-list');
const toBoardType = containerEl.dataset.boardType;
if (toBoardType) {
const fromBoardType = this.list.type;
if ((fromBoardType === 'assignee' && toBoardType === 'label') ||
(fromBoardType === 'label' && toBoardType === 'assignee')) {
return 'clone';
}
}
}
return true;
},
revertClone: true,
},
onStart: (e) => { onStart: (e) => {
const card = this.$refs.issue[e.oldIndex]; const card = this.$refs.issue[e.oldIndex];
@ -169,21 +205,22 @@ export default {
<template> <template>
<div class="board-list-component"> <div class="board-list-component">
<div <div
v-if="loading"
class="board-list-loading text-center" class="board-list-loading text-center"
aria-label="Loading issues" aria-label="Loading issues">
v-if="loading">
<loading-icon /> <loading-icon />
</div> </div>
<board-new-issue <board-new-issue
v-if="list.type !== 'closed' && showIssueForm"
:group-id="groupId" :group-id="groupId"
:list="list" :list="list"/>
v-if="list.type !== 'closed' && showIssueForm"/>
<ul <ul
class="board-list"
v-show="!loading" v-show="!loading"
ref="list" ref="list"
:data-board="list.id" :data-board="list.id"
:class="{ 'is-smaller': showIssueForm }"> :data-board-type="list.type"
:class="{ 'is-smaller': showIssueForm }"
class="board-list js-board-list">
<board-card <board-card
v-for="(issue, index) in issues" v-for="(issue, index) in issues"
ref="issue" ref="issue"
@ -196,8 +233,8 @@ export default {
:disabled="disabled" :disabled="disabled"
:key="issue.id" /> :key="issue.id" />
<li <li
class="board-list-count text-center"
v-if="showCount" v-if="showCount"
class="board-list-count text-center"
data-issue-id="-1"> data-issue-id="-1">
<loading-icon <loading-icon
v-show="list.loadingMore" v-show="list.loadingMore"

View file

@ -49,11 +49,12 @@ export default {
this.error = false; this.error = false;
const labels = this.list.label ? [this.list.label] : []; const labels = this.list.label ? [this.list.label] : [];
const assignees = this.list.assignee ? [this.list.assignee] : [];
const issue = new ListIssue({ const issue = new ListIssue({
title: this.title, title: this.title,
labels, labels,
subscribed: true, subscribed: true,
assignees: [], assignees,
project_id: this.selectedProject.id, project_id: this.selectedProject.id,
}); });
@ -92,29 +93,29 @@ export default {
<template> <template>
<div class="board-new-issue-form"> <div class="board-new-issue-form">
<div class="card"> <div class="board-card">
<form @submit="submit($event)"> <form @submit="submit($event)">
<div <div
class="flash-container"
v-if="error" v-if="error"
class="flash-container"
> >
<div class="flash-alert"> <div class="flash-alert">
An error occurred. Please try again. An error occurred. Please try again.
</div> </div>
</div> </div>
<label <label
class="label-light"
:for="list.id + '-title'" :for="list.id + '-title'"
class="label-light"
> >
Title Title
</label> </label>
<input <input
ref="input"
v-model="title"
:id="list.id + '-title'"
class="form-control" class="form-control"
type="text" type="text"
v-model="title"
ref="input"
autocomplete="off" autocomplete="off"
:id="list.id + '-title'"
/> />
<project-select <project-select
v-if="groupId" v-if="groupId"
@ -122,15 +123,15 @@ export default {
/> />
<div class="clearfix prepend-top-10"> <div class="clearfix prepend-top-10">
<button <button
class="btn btn-success pull-left"
type="submit"
:disabled="disabled"
ref="submit-button" ref="submit-button"
:disabled="disabled"
class="btn btn-success float-left"
type="submit"
> >
Submit issue Submit issue
</button> </button>
<button <button
class="btn btn-default pull-right" class="btn btn-default float-right"
type="button" type="button"
@click="cancel" @click="cancel"
> >
@ -141,4 +142,3 @@ export default {
</div> </div>
</div> </div>
</template> </template>

View file

@ -1,4 +1,4 @@
/* eslint-disable comma-dangle, space-before-function-paren, no-new */ /* eslint-disable comma-dangle, no-new */
import $ from 'jquery'; import $ from 'jquery';
import Vue from 'vue'; import Vue from 'vue';
@ -6,13 +6,13 @@ import Flash from '../../flash';
import { __ } from '../../locale'; import { __ } from '../../locale';
import Sidebar from '../../right_sidebar'; import Sidebar from '../../right_sidebar';
import eventHub from '../../sidebar/event_hub'; import eventHub from '../../sidebar/event_hub';
import assigneeTitle from '../../sidebar/components/assignees/assignee_title.vue'; import AssigneeTitle from '../../sidebar/components/assignees/assignee_title.vue';
import assignees from '../../sidebar/components/assignees/assignees.vue'; import Assignees from '../../sidebar/components/assignees/assignees.vue';
import DueDateSelectors from '../../due_date_select'; import DueDateSelectors from '../../due_date_select';
import './sidebar/remove_issue'; import RemoveBtn from './sidebar/remove_issue.vue';
import IssuableContext from '../../issuable_context'; import IssuableContext from '../../issuable_context';
import LabelsSelect from '../../labels_select'; import LabelsSelect from '../../labels_select';
import subscriptions from '../../sidebar/components/subscriptions/subscriptions.vue'; import Subscriptions from '../../sidebar/components/subscriptions/subscriptions.vue';
import MilestoneSelect from '../../milestone_select'; import MilestoneSelect from '../../milestone_select';
const Store = gl.issueBoards.BoardsStore; const Store = gl.issueBoards.BoardsStore;
@ -21,8 +21,17 @@ window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {}; window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.BoardSidebar = Vue.extend({ gl.issueBoards.BoardSidebar = Vue.extend({
components: {
AssigneeTitle,
Assignees,
RemoveBtn,
Subscriptions,
},
props: { props: {
currentUser: Object currentUser: {
type: Object,
default: () => ({}),
},
}, },
data() { data() {
return { return {
@ -64,6 +73,26 @@ gl.issueBoards.BoardSidebar = Vue.extend({
deep: true deep: true
}, },
}, },
created () {
// Get events from glDropdown
eventHub.$on('sidebar.removeAssignee', this.removeAssignee);
eventHub.$on('sidebar.addAssignee', this.addAssignee);
eventHub.$on('sidebar.removeAllAssignees', this.removeAllAssignees);
eventHub.$on('sidebar.saveAssignees', this.saveAssignees);
},
beforeDestroy() {
eventHub.$off('sidebar.removeAssignee', this.removeAssignee);
eventHub.$off('sidebar.addAssignee', this.addAssignee);
eventHub.$off('sidebar.removeAllAssignees', this.removeAllAssignees);
eventHub.$off('sidebar.saveAssignees', this.saveAssignees);
},
mounted () {
new IssuableContext(this.currentUser);
new MilestoneSelect();
new DueDateSelectors();
new LabelsSelect();
new Sidebar();
},
methods: { methods: {
closeSidebar () { closeSidebar () {
this.detail.issue = {}; this.detail.issue = {};
@ -97,30 +126,4 @@ gl.issueBoards.BoardSidebar = Vue.extend({
}); });
}, },
}, },
created () {
// Get events from glDropdown
eventHub.$on('sidebar.removeAssignee', this.removeAssignee);
eventHub.$on('sidebar.addAssignee', this.addAssignee);
eventHub.$on('sidebar.removeAllAssignees', this.removeAllAssignees);
eventHub.$on('sidebar.saveAssignees', this.saveAssignees);
},
beforeDestroy() {
eventHub.$off('sidebar.removeAssignee', this.removeAssignee);
eventHub.$off('sidebar.addAssignee', this.addAssignee);
eventHub.$off('sidebar.removeAllAssignees', this.removeAllAssignees);
eventHub.$off('sidebar.saveAssignees', this.saveAssignees);
},
mounted () {
new IssuableContext(this.currentUser);
new MilestoneSelect();
new DueDateSelectors();
new LabelsSelect();
new Sidebar();
},
components: {
assigneeTitle,
assignees,
removeBtn: gl.issueBoards.RemoveIssueBtn,
subscriptions,
},
}); });

View file

@ -1,195 +0,0 @@
import $ from 'jquery';
import Vue from 'vue';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import eventHub from '../eventhub';
const Store = gl.issueBoards.BoardsStore;
window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.IssueCardInner = Vue.extend({
props: {
issue: {
type: Object,
required: true,
},
issueLinkBase: {
type: String,
required: true,
},
list: {
type: Object,
required: false,
default: () => ({}),
},
rootPath: {
type: String,
required: true,
},
updateFilters: {
type: Boolean,
required: false,
default: false,
},
groupId: {
type: Number,
required: false,
},
},
data() {
return {
limitBeforeCounter: 3,
maxRender: 4,
maxCounter: 99,
};
},
components: {
UserAvatarLink,
},
computed: {
numberOverLimit() {
return this.issue.assignees.length - this.limitBeforeCounter;
},
assigneeCounterTooltip() {
return `${this.assigneeCounterLabel} more`;
},
assigneeCounterLabel() {
if (this.numberOverLimit > this.maxCounter) {
return `${this.maxCounter}+`;
}
return `+${this.numberOverLimit}`;
},
shouldRenderCounter() {
if (this.issue.assignees.length <= this.maxRender) {
return false;
}
return this.issue.assignees.length > this.numberOverLimit;
},
issueId() {
if (this.issue.iid) {
return `#${this.issue.iid}`;
}
return false;
},
showLabelFooter() {
return this.issue.labels.find(l => this.showLabel(l)) !== undefined;
},
},
methods: {
isIndexLessThanlimit(index) {
return index < this.limitBeforeCounter;
},
shouldRenderAssignee(index) {
// Eg. maxRender is 4,
// Render up to all 4 assignees if there are only 4 assigness
// Otherwise render up to the limitBeforeCounter
if (this.issue.assignees.length <= this.maxRender) {
return index < this.maxRender;
}
return index < this.limitBeforeCounter;
},
assigneeUrl(assignee) {
return `${this.rootPath}${assignee.username}`;
},
assigneeUrlTitle(assignee) {
return `Assigned to ${assignee.name}`;
},
avatarUrlTitle(assignee) {
return `Avatar for ${assignee.name}`;
},
showLabel(label) {
if (!label.id) return false;
return true;
},
filterByLabel(label, e) {
if (!this.updateFilters) return;
const filterPath = gl.issueBoards.BoardsStore.filter.path.split('&');
const labelTitle = encodeURIComponent(label.title);
const param = `label_name[]=${labelTitle}`;
const labelIndex = filterPath.indexOf(param);
$(e.currentTarget).tooltip('hide');
if (labelIndex === -1) {
filterPath.push(param);
} else {
filterPath.splice(labelIndex, 1);
}
gl.issueBoards.BoardsStore.filter.path = filterPath.join('&');
Store.updateFiltersUrl();
eventHub.$emit('updateTokens');
},
labelStyle(label) {
return {
backgroundColor: label.color,
color: label.textColor,
};
},
},
template: `
<div>
<div class="card-header">
<h4 class="card-title">
<i
class="fa fa-eye-slash confidential-icon"
v-if="issue.confidential"
aria-hidden="true"
/>
<a
class="js-no-trigger"
:href="issue.path"
:title="issue.title">{{ issue.title }}</a>
<span
class="card-number"
v-if="issueId"
>
{{ issue.referencePath }}
</span>
</h4>
<div class="card-assignee">
<user-avatar-link
v-for="(assignee, index) in issue.assignees"
:key="assignee.id"
v-if="shouldRenderAssignee(index)"
class="js-no-trigger"
:link-href="assigneeUrl(assignee)"
:img-alt="avatarUrlTitle(assignee)"
:img-src="assignee.avatar"
:tooltip-text="assigneeUrlTitle(assignee)"
tooltip-placement="bottom"
/>
<span
class="avatar-counter has-tooltip"
:title="assigneeCounterTooltip"
v-if="shouldRenderCounter"
>
{{ assigneeCounterLabel }}
</span>
</div>
</div>
<div
class="card-footer"
v-if="showLabelFooter"
>
<button
class="label color-label has-tooltip"
v-for="label in issue.labels"
type="button"
v-if="showLabel(label)"
@click="filterByLabel(label, $event)"
:style="labelStyle(label)"
:title="label.description"
data-container="body">
{{ label.title }}
</button>
</div>
</div>
`,
});

View file

@ -0,0 +1,202 @@
<script>
import $ from 'jquery';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import eventHub from '../eventhub';
import tooltip from '../../vue_shared/directives/tooltip';
const Store = gl.issueBoards.BoardsStore;
export default {
components: {
UserAvatarLink,
},
directives: {
tooltip,
},
props: {
issue: {
type: Object,
required: true,
},
issueLinkBase: {
type: String,
required: true,
},
list: {
type: Object,
required: false,
default: () => ({}),
},
rootPath: {
type: String,
required: true,
},
updateFilters: {
type: Boolean,
required: false,
default: false,
},
groupId: {
type: Number,
required: false,
default: null,
},
},
data() {
return {
limitBeforeCounter: 3,
maxRender: 4,
maxCounter: 99,
};
},
computed: {
numberOverLimit() {
return this.issue.assignees.length - this.limitBeforeCounter;
},
assigneeCounterTooltip() {
return `${this.assigneeCounterLabel} more`;
},
assigneeCounterLabel() {
if (this.numberOverLimit > this.maxCounter) {
return `${this.maxCounter}+`;
}
return `+${this.numberOverLimit}`;
},
shouldRenderCounter() {
if (this.issue.assignees.length <= this.maxRender) {
return false;
}
return this.issue.assignees.length > this.numberOverLimit;
},
issueId() {
if (this.issue.iid) {
return `#${this.issue.iid}`;
}
return false;
},
showLabelFooter() {
return this.issue.labels.find(l => this.showLabel(l)) !== undefined;
},
},
methods: {
isIndexLessThanlimit(index) {
return index < this.limitBeforeCounter;
},
shouldRenderAssignee(index) {
// Eg. maxRender is 4,
// Render up to all 4 assignees if there are only 4 assigness
// Otherwise render up to the limitBeforeCounter
if (this.issue.assignees.length <= this.maxRender) {
return index < this.maxRender;
}
return index < this.limitBeforeCounter;
},
assigneeUrl(assignee) {
return `${this.rootPath}${assignee.username}`;
},
assigneeUrlTitle(assignee) {
return `Assigned to ${assignee.name}`;
},
avatarUrlTitle(assignee) {
return `Avatar for ${assignee.name}`;
},
showLabel(label) {
if (!label.id) return false;
return true;
},
filterByLabel(label, e) {
if (!this.updateFilters) return;
const filterPath = gl.issueBoards.BoardsStore.filter.path.split('&');
const labelTitle = encodeURIComponent(label.title);
const param = `label_name[]=${labelTitle}`;
const labelIndex = filterPath.indexOf(param);
$(e.currentTarget).tooltip('hide');
if (labelIndex === -1) {
filterPath.push(param);
} else {
filterPath.splice(labelIndex, 1);
}
gl.issueBoards.BoardsStore.filter.path = filterPath.join('&');
Store.updateFiltersUrl();
eventHub.$emit('updateTokens');
},
labelStyle(label) {
return {
backgroundColor: label.color,
color: label.textColor,
};
},
},
};
</script>
<template>
<div>
<div class="board-card-header">
<h4 class="board-card-title">
<i
v-if="issue.confidential"
class="fa fa-eye-slash confidential-icon"
aria-hidden="true"
></i>
<a
:href="issue.path"
:title="issue.title"
class="js-no-trigger">{{ issue.title }}</a>
<span
v-if="issueId"
class="board-card-number"
>
{{ issue.referencePath }}
</span>
</h4>
<div class="board-card-assignee">
<user-avatar-link
v-for="(assignee, index) in issue.assignees"
v-if="shouldRenderAssignee(index)"
:key="assignee.id"
:link-href="assigneeUrl(assignee)"
:img-alt="avatarUrlTitle(assignee)"
:img-src="assignee.avatar"
:tooltip-text="assigneeUrlTitle(assignee)"
class="js-no-trigger"
tooltip-placement="bottom"
/>
<span
v-tooltip
v-if="shouldRenderCounter"
:title="assigneeCounterTooltip"
class="avatar-counter"
>
{{ assigneeCounterLabel }}
</span>
</div>
</div>
<div
v-if="showLabelFooter"
class="board-card-footer"
>
<button
v-tooltip
v-for="label in issue.labels"
v-if="showLabel(label)"
:key="label.id"
:style="labelStyle(label)"
:title="label.description"
class="badge color-label"
type="button"
data-container="body"
@click="filterByLabel(label, $event)"
>
{{ label.title }}
</button>
</div>
</div>
</template>

View file

@ -1,12 +1,9 @@
import Vue from 'vue'; <script>
import ModalStore from '../../stores/modal_store'; import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins'; import modalMixin from '../../mixins/modal_mixins';
gl.issueBoards.ModalEmptyState = Vue.extend({ export default {
mixins: [modalMixin], mixins: [modalMixin],
data() {
return ModalStore.store;
},
props: { props: {
newIssuePath: { newIssuePath: {
type: String, type: String,
@ -17,6 +14,9 @@ gl.issueBoards.ModalEmptyState = Vue.extend({
required: true, required: true,
}, },
}, },
data() {
return ModalStore.store;
},
computed: { computed: {
contents() { contents() {
const obj = { const obj = {
@ -38,32 +38,36 @@ gl.issueBoards.ModalEmptyState = Vue.extend({
return obj; return obj;
}, },
}, },
template: ` };
</script>
<template>
<section class="empty-state"> <section class="empty-state">
<div class="row"> <div class="row">
<div class="col-xs-12 col-sm-6 col-sm-push-6"> <div class="col-12 col-md-6 order-md-last">
<aside class="svg-content"><img :src="emptyStateSvg"/></aside> <aside class="svg-content"><img :src="emptyStateSvg"/></aside>
</div> </div>
<div class="col-xs-12 col-sm-6 col-sm-pull-6"> <div class="col-12 col-md-6 order-md-first">
<div class="text-content"> <div class="text-content">
<h4>{{ contents.title }}</h4> <h4>{{ contents.title }}</h4>
<p v-html="contents.content"></p> <p v-html="contents.content"></p>
<a <a
v-if="activeTab === 'all'"
:href="newIssuePath" :href="newIssuePath"
class="btn btn-success btn-inverted" class="btn btn-success btn-inverted"
v-if="activeTab === 'all'"> >
New issue New issue
</a> </a>
<button <button
type="button" v-if="activeTab === 'selected'"
class="btn btn-default" class="btn btn-default"
type="button"
@click="changeTab('all')" @click="changeTab('all')"
v-if="activeTab === 'selected'"> >
Open issues Open issues
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
`, </template>
});

View file

@ -1,12 +1,15 @@
import Vue from 'vue'; <script>
import Flash from '../../../flash'; import Flash from '../../../flash';
import { __ } from '../../../locale'; import { __ } from '../../../locale';
import './lists_dropdown'; import ListsDropdown from './lists_dropdown.vue';
import { pluralize } from '../../../lib/utils/text_utility'; import { pluralize } from '../../../lib/utils/text_utility';
import ModalStore from '../../stores/modal_store'; import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins'; import modalMixin from '../../mixins/modal_mixins';
gl.issueBoards.ModalFooter = Vue.extend({ export default {
components: {
ListsDropdown,
},
mixins: [modalMixin], mixins: [modalMixin],
data() { data() {
return { return {
@ -25,16 +28,22 @@ gl.issueBoards.ModalFooter = Vue.extend({
}, },
}, },
methods: { methods: {
buildUpdateRequest(list) {
return {
add_label_ids: [list.label.id],
};
},
addIssues() { addIssues() {
const firstListIndex = 1; const firstListIndex = 1;
const list = this.modal.selectedList || this.state.lists[firstListIndex]; const list = this.modal.selectedList || this.state.lists[firstListIndex];
const selectedIssues = ModalStore.getSelectedIssues(); const selectedIssues = ModalStore.getSelectedIssues();
const issueIds = selectedIssues.map(issue => issue.id); const issueIds = selectedIssues.map(issue => issue.id);
const req = this.buildUpdateRequest(list);
// Post the data to the backend // Post the data to the backend
gl.boardService.bulkUpdate(issueIds, { gl.boardService
add_label_ids: [list.label.id], .bulkUpdate(issueIds, req)
}).catch(() => { .catch(() => {
Flash(__('Failed to update issues, please try again.')); Flash(__('Failed to update issues, please try again.'));
selectedIssues.forEach((issue) => { selectedIssues.forEach((issue) => {
@ -52,31 +61,32 @@ gl.issueBoards.ModalFooter = Vue.extend({
this.toggleModal(false); this.toggleModal(false);
}, },
}, },
components: { };
'lists-dropdown': gl.issueBoards.ModalFooterListsDropdown, </script>
}, <template>
template: `
<footer <footer
class="form-actions add-issues-footer"> class="form-actions add-issues-footer"
<div class="pull-left"> >
<div class="float-left">
<button <button
:disabled="submitDisabled"
class="btn btn-success" class="btn btn-success"
type="button" type="button"
:disabled="submitDisabled" @click="addIssues"
@click="addIssues"> >
{{ submitText }} {{ submitText }}
</button> </button>
<span class="inline add-issues-footer-to-list"> <span class="inline add-issues-footer-to-list">
to list to list
</span> </span>
<lists-dropdown></lists-dropdown> <lists-dropdown/>
</div> </div>
<button <button
class="btn btn-default pull-right" class="btn btn-default float-right"
type="button" type="button"
@click="toggleModal(false)"> @click="toggleModal(false)"
>
Cancel Cancel
</button> </button>
</footer> </footer>
`, </template>
});

View file

@ -1,79 +0,0 @@
import Vue from 'vue';
import modalFilters from './filters';
import './tabs';
import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins';
gl.issueBoards.ModalHeader = Vue.extend({
mixins: [modalMixin],
props: {
projectId: {
type: Number,
required: true,
},
milestonePath: {
type: String,
required: true,
},
labelPath: {
type: String,
required: true,
},
},
data() {
return ModalStore.store;
},
computed: {
selectAllText() {
if (ModalStore.selectedCount() !== this.issues.length || this.issues.length === 0) {
return 'Select all';
}
return 'Deselect all';
},
showSearch() {
return this.activeTab === 'all' && !this.loading && this.issuesCount > 0;
},
},
methods: {
toggleAll() {
this.$refs.selectAllBtn.blur();
ModalStore.toggleAll();
},
},
components: {
'modal-tabs': gl.issueBoards.ModalTabs,
modalFilters,
},
template: `
<div>
<header class="add-issues-header form-actions">
<h2>
Add issues
<button
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
@click="toggleModal(false)">
<span aria-hidden="true">×</span>
</button>
</h2>
</header>
<modal-tabs v-if="!loading && issuesCount > 0"></modal-tabs>
<div
class="add-issues-search append-bottom-10"
v-if="showSearch">
<modal-filters :store="filter" />
<button
type="button"
class="btn btn-success btn-inverted prepend-left-10"
ref="selectAllBtn"
@click="toggleAll">
{{ selectAllText }}
</button>
</div>
</div>
`,
});

View file

@ -0,0 +1,82 @@
<script>
import ModalFilters from './filters';
import ModalTabs from './tabs.vue';
import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins';
export default {
components: {
ModalTabs,
ModalFilters,
},
mixins: [modalMixin],
props: {
projectId: {
type: Number,
required: true,
},
milestonePath: {
type: String,
required: true,
},
labelPath: {
type: String,
required: true,
},
},
data() {
return ModalStore.store;
},
computed: {
selectAllText() {
if (ModalStore.selectedCount() !== this.issues.length || this.issues.length === 0) {
return 'Select all';
}
return 'Deselect all';
},
showSearch() {
return this.activeTab === 'all' && !this.loading && this.issuesCount > 0;
},
},
methods: {
toggleAll() {
this.$refs.selectAllBtn.blur();
ModalStore.toggleAll();
},
},
};
</script>
<template>
<div>
<header class="add-issues-header form-actions">
<h2>
Add issues
<button
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
@click="toggleModal(false)"
>
<span aria-hidden="true">×</span>
</button>
</h2>
</header>
<modal-tabs v-if="!loading && issuesCount > 0"/>
<div
v-if="showSearch"
class="add-issues-search append-bottom-10">
<modal-filters :store="filter" />
<button
ref="selectAllBtn"
type="button"
class="btn btn-success btn-inverted prepend-left-10"
@click="toggleAll"
>
{{ selectAllText }}
</button>
</div>
</div>
</template>

View file

@ -1,171 +0,0 @@
/* global ListIssue */
import Vue from 'vue';
import queryData from '~/boards/utils/query_data';
import loadingIcon from '~/vue_shared/components/loading_icon.vue';
import './header';
import './list';
import './footer';
import './empty_state';
import ModalStore from '../../stores/modal_store';
gl.issueBoards.IssuesModal = Vue.extend({
props: {
newIssuePath: {
type: String,
required: true,
},
emptyStateSvg: {
type: String,
required: true,
},
issueLinkBase: {
type: String,
required: true,
},
rootPath: {
type: String,
required: true,
},
projectId: {
type: Number,
required: true,
},
milestonePath: {
type: String,
required: true,
},
labelPath: {
type: String,
required: true,
},
},
data() {
return ModalStore.store;
},
watch: {
page() {
this.loadIssues();
},
showAddIssuesModal() {
if (this.showAddIssuesModal && !this.issues.length) {
this.loading = true;
const loadingDone = () => {
this.loading = false;
};
this.loadIssues()
.then(loadingDone)
.catch(loadingDone);
} else if (!this.showAddIssuesModal) {
this.issues = [];
this.selectedIssues = [];
this.issuesCount = false;
}
},
filter: {
handler() {
if (this.$el.tagName) {
this.page = 1;
this.filterLoading = true;
const loadingDone = () => {
this.filterLoading = false;
};
this.loadIssues(true)
.then(loadingDone)
.catch(loadingDone);
}
},
deep: true,
},
},
methods: {
loadIssues(clearIssues = false) {
if (!this.showAddIssuesModal) return false;
return gl.boardService.getBacklog(queryData(this.filter.path, {
page: this.page,
per: this.perPage,
}))
.then(res => res.data)
.then((data) => {
if (clearIssues) {
this.issues = [];
}
data.issues.forEach((issueObj) => {
const issue = new ListIssue(issueObj);
const foundSelectedIssue = ModalStore.findSelectedIssue(issue);
issue.selected = !!foundSelectedIssue;
this.issues.push(issue);
});
this.loadingNewPage = false;
if (!this.issuesCount) {
this.issuesCount = data.size;
}
}).catch(() => {
// TODO: handle request error
});
},
},
computed: {
showList() {
if (this.activeTab === 'selected') {
return this.selectedIssues.length > 0;
}
return this.issuesCount > 0;
},
showEmptyState() {
if (!this.loading && this.issuesCount === 0) {
return true;
}
return this.activeTab === 'selected' && this.selectedIssues.length === 0;
},
},
created() {
this.page = 1;
},
components: {
'modal-header': gl.issueBoards.ModalHeader,
'modal-list': gl.issueBoards.ModalList,
'modal-footer': gl.issueBoards.ModalFooter,
'empty-state': gl.issueBoards.ModalEmptyState,
loadingIcon,
},
template: `
<div
class="add-issues-modal"
v-if="showAddIssuesModal">
<div class="add-issues-container">
<modal-header
:project-id="projectId"
:milestone-path="milestonePath"
:label-path="labelPath">
</modal-header>
<modal-list
:issue-link-base="issueLinkBase"
:root-path="rootPath"
:empty-state-svg="emptyStateSvg"
v-if="!loading && showList && !filterLoading"></modal-list>
<empty-state
v-if="showEmptyState"
:new-issue-path="newIssuePath"
:empty-state-svg="emptyStateSvg"></empty-state>
<section
class="add-issues-list text-center"
v-if="loading || filterLoading">
<div class="add-issues-list-loading">
<loading-icon />
</div>
</section>
<modal-footer></modal-footer>
</div>
</div>
`,
});

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