New upstream version 11.4.9+dfsg
25
.babelrc
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"presets": [["latest", { "es2015": { "modules": false } }], "stage-2"],
|
|
||||||
"env": {
|
|
||||||
"karma": {
|
|
||||||
"plugins": ["rewire"]
|
|
||||||
},
|
|
||||||
"coverage": {
|
|
||||||
"plugins": [
|
|
||||||
[
|
|
||||||
"istanbul",
|
|
||||||
{
|
|
||||||
"exclude": ["spec/javascripts/**/*", "app/assets/javascripts/locale/**/app.js"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"transform-define",
|
|
||||||
{
|
|
||||||
"process.env.BABEL_ENV": "coverage"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"rewire"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
38
.babelrc.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
const BABEL_ENV = process.env.BABEL_ENV || process.env.NODE_ENV || null;
|
||||||
|
|
||||||
|
const presets = [
|
||||||
|
[
|
||||||
|
'@babel/preset-env',
|
||||||
|
{
|
||||||
|
modules: false,
|
||||||
|
targets: {
|
||||||
|
ie: '11',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
// include stage 3 proposals
|
||||||
|
const plugins = [
|
||||||
|
'@babel/plugin-syntax-dynamic-import',
|
||||||
|
'@babel/plugin-syntax-import-meta',
|
||||||
|
'@babel/plugin-proposal-class-properties',
|
||||||
|
'@babel/plugin-proposal-json-strings',
|
||||||
|
];
|
||||||
|
|
||||||
|
// add code coverage tooling if necessary
|
||||||
|
if (BABEL_ENV === 'coverage') {
|
||||||
|
plugins.push([
|
||||||
|
'babel-plugin-istanbul',
|
||||||
|
{
|
||||||
|
exclude: ['spec/javascripts/**/*', 'app/assets/javascripts/locale/**/app.js'],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add rewire support when running tests
|
||||||
|
if (BABEL_ENV === 'karma' || BABEL_ENV === 'coverage') {
|
||||||
|
plugins.push('babel-plugin-rewire');
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { presets, plugins };
|
|
@ -56,6 +56,10 @@ rules:
|
||||||
component: always
|
component: always
|
||||||
svg: always
|
svg: always
|
||||||
math: always
|
math: always
|
||||||
|
camelcase:
|
||||||
|
- error
|
||||||
|
- properties: never
|
||||||
|
ignoreDestructuring: true
|
||||||
## Conflicting rules with prettier:
|
## Conflicting rules with prettier:
|
||||||
space-before-function-paren: off
|
space-before-function-paren: off
|
||||||
curly: off
|
curly: off
|
||||||
|
@ -63,7 +67,7 @@ rules:
|
||||||
function-paren-newline: off
|
function-paren-newline: off
|
||||||
object-curly-newline: off
|
object-curly-newline: off
|
||||||
padded-blocks: off
|
padded-blocks: off
|
||||||
# Disabled for now, to make the eslint 3 -> eslint 4 update smoother
|
# Disabled for now, to make the eslint 3 -> eslint 5 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 rule. We are using the old for now: https://eslint.org/docs/user-guide/migrating-to-4.0.0#indent-rewrite
|
||||||
indent: off
|
indent: off
|
||||||
indent-legacy:
|
indent-legacy:
|
||||||
|
@ -78,3 +82,18 @@ rules:
|
||||||
FunctionExpression:
|
FunctionExpression:
|
||||||
parameters: 1
|
parameters: 1
|
||||||
body: 1
|
body: 1
|
||||||
|
# Disabled for now, to make the airbnb-base 12.1.0 -> 13.1.0 update smoother
|
||||||
|
operator-linebreak: off
|
||||||
|
implicit-arrow-linebreak: off
|
||||||
|
no-else-return:
|
||||||
|
- error
|
||||||
|
- allowElseIf: true
|
||||||
|
import/no-useless-path-segments: off
|
||||||
|
lines-between-class-members: off
|
||||||
|
# Disabled for now, to make the plugin-vue 4.5 -> 5.0 update smoother
|
||||||
|
vue/html-closing-bracket-newline: off
|
||||||
|
vue/html-closing-bracket-spacing: off
|
||||||
|
vue/no-confusing-v-for-v-if: error
|
||||||
|
vue/no-unused-components: off
|
||||||
|
vue/no-use-v-if-with-v-for: off
|
||||||
|
vue/no-v-html: off
|
||||||
|
|
1
.gitignore
vendored
|
@ -78,3 +78,4 @@ eslint-report.html
|
||||||
/.gitlab_pages_secret
|
/.gitlab_pages_secret
|
||||||
package-lock.json
|
package-lock.json
|
||||||
/junit_rspec.xml
|
/junit_rspec.xml
|
||||||
|
/junit_karma.xml
|
||||||
|
|
|
@ -67,10 +67,7 @@ stages:
|
||||||
|
|
||||||
.use-pg: &use-pg
|
.use-pg: &use-pg
|
||||||
services:
|
services:
|
||||||
# As of Jan 2018, we don't have a strong reason to upgrade to 9.6 for CI yet,
|
- postgres:9.6
|
||||||
# so using the least common denominator ensures backwards compatibility
|
|
||||||
# (as many users are still using 9.2).
|
|
||||||
- postgres:9.2
|
|
||||||
- redis:alpine
|
- redis:alpine
|
||||||
|
|
||||||
.use-mysql: &use-mysql
|
.use-mysql: &use-mysql
|
||||||
|
@ -95,7 +92,7 @@ stages:
|
||||||
|
|
||||||
# Skip all jobs except the ones that begin with 'docs/'.
|
# Skip all jobs except the ones that begin with 'docs/'.
|
||||||
# Used for commits including ONLY documentation changes.
|
# Used for commits including ONLY documentation changes.
|
||||||
# https://docs.gitlab.com/ce/development/writing_documentation.html#testing
|
# https://docs.gitlab.com/ce/development/documentation/#testing
|
||||||
.except-docs: &except-docs
|
.except-docs: &except-docs
|
||||||
except:
|
except:
|
||||||
- /(^docs[\/-].*|.*-docs$)/
|
- /(^docs[\/-].*|.*-docs$)/
|
||||||
|
@ -130,7 +127,6 @@ stages:
|
||||||
|
|
||||||
.single-script-job: &single-script-job
|
.single-script-job: &single-script-job
|
||||||
image: ruby:2.4-alpine
|
image: ruby:2.4-alpine
|
||||||
before_script: []
|
|
||||||
stage: test
|
stage: test
|
||||||
cache: {}
|
cache: {}
|
||||||
dependencies: []
|
dependencies: []
|
||||||
|
@ -259,6 +255,7 @@ package-and-qa:
|
||||||
SCRIPT_NAME: trigger-build
|
SCRIPT_NAME: trigger-build
|
||||||
retry: 0
|
retry: 0
|
||||||
script:
|
script:
|
||||||
|
- gem install gitlab --no-document
|
||||||
- ./$SCRIPT_NAME omnibus
|
- ./$SCRIPT_NAME omnibus
|
||||||
when: manual
|
when: manual
|
||||||
only:
|
only:
|
||||||
|
@ -285,7 +282,7 @@ review-docs-deploy-manual:
|
||||||
<<: *review-docs
|
<<: *review-docs
|
||||||
stage: build
|
stage: build
|
||||||
script:
|
script:
|
||||||
- gem install gitlab --no-ri --no-rdoc
|
- gem install gitlab --no-document
|
||||||
- ./$SCRIPT_NAME deploy
|
- ./$SCRIPT_NAME deploy
|
||||||
when: manual
|
when: manual
|
||||||
only:
|
only:
|
||||||
|
@ -299,7 +296,7 @@ review-docs-deploy:
|
||||||
<<: *review-docs
|
<<: *review-docs
|
||||||
stage: post-test
|
stage: post-test
|
||||||
script:
|
script:
|
||||||
- gem install gitlab --no-ri --no-rdoc
|
- gem install gitlab --no-document
|
||||||
- ./$SCRIPT_NAME deploy
|
- ./$SCRIPT_NAME deploy
|
||||||
only:
|
only:
|
||||||
- /(^docs[\/-].*|.*-docs$)/@gitlab-org/gitlab-ce
|
- /(^docs[\/-].*|.*-docs$)/@gitlab-org/gitlab-ce
|
||||||
|
@ -314,7 +311,7 @@ review-docs-cleanup:
|
||||||
name: review-docs/$CI_COMMIT_REF_SLUG
|
name: review-docs/$CI_COMMIT_REF_SLUG
|
||||||
action: stop
|
action: stop
|
||||||
script:
|
script:
|
||||||
- gem install gitlab --no-ri --no-rdoc
|
- gem install gitlab --no-document
|
||||||
- ./$SCRIPT_NAME cleanup
|
- ./$SCRIPT_NAME cleanup
|
||||||
when: manual
|
when: manual
|
||||||
only:
|
only:
|
||||||
|
@ -333,8 +330,8 @@ cloud-native-image:
|
||||||
GIT_DEPTH: "1"
|
GIT_DEPTH: "1"
|
||||||
cache: {}
|
cache: {}
|
||||||
script:
|
script:
|
||||||
- gem install gitlab --no-ri --no-rdoc
|
- gem install gitlab --no-document
|
||||||
- BUILD_TRIGGER_TOKEN=$CI_JOB_TOKEN scripts/trigger-build cng
|
- CNG_PROJECT_PATH="gitlab-org/build/CNG" BUILD_TRIGGER_TOKEN=$CI_JOB_TOKEN ./scripts/trigger-build cng
|
||||||
only:
|
only:
|
||||||
- tags@gitlab-org/gitlab-ce
|
- tags@gitlab-org/gitlab-ce
|
||||||
- tags@gitlab-org/gitlab-ee
|
- tags@gitlab-org/gitlab-ee
|
||||||
|
@ -366,7 +363,7 @@ update-tests-metadata:
|
||||||
- rspec_flaky/
|
- rspec_flaky/
|
||||||
policy: push
|
policy: push
|
||||||
script:
|
script:
|
||||||
- retry gem install fog-aws mime-types activesupport --no-ri --no-rdoc
|
- retry gem install fog-aws mime-types activesupport --no-document
|
||||||
- scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec-pg_node_*.json
|
- scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec-pg_node_*.json
|
||||||
- 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}
|
||||||
|
@ -444,10 +441,10 @@ setup-test-env:
|
||||||
- vendor/gitaly-ruby
|
- vendor/gitaly-ruby
|
||||||
|
|
||||||
danger-review:
|
danger-review:
|
||||||
|
<<: *pull-cache
|
||||||
image: registry.gitlab.com/gitlab-org/gitlab-build-images:danger
|
image: registry.gitlab.com/gitlab-org/gitlab-build-images:danger
|
||||||
stage: test
|
stage: test
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
cache: {}
|
|
||||||
dependencies: []
|
dependencies: []
|
||||||
before_script: []
|
before_script: []
|
||||||
only:
|
only:
|
||||||
|
@ -461,6 +458,8 @@ danger-review:
|
||||||
- $CI_COMMIT_REF_NAME =~ /.*-stable(-ee)?-prepare-.*/
|
- $CI_COMMIT_REF_NAME =~ /.*-stable(-ee)?-prepare-.*/
|
||||||
script:
|
script:
|
||||||
- git version
|
- git version
|
||||||
|
- node --version
|
||||||
|
- yarn install --frozen-lockfile --cache-folder .yarn-cache
|
||||||
- danger --fail-on-errors=true
|
- danger --fail-on-errors=true
|
||||||
|
|
||||||
rspec-pg 0 30: *rspec-metadata-pg
|
rspec-pg 0 30: *rspec-metadata-pg
|
||||||
|
@ -607,7 +606,7 @@ static-analysis:
|
||||||
docs lint:
|
docs lint:
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
<<: *except-qa
|
<<: *except-qa
|
||||||
image: "registry.gitlab.com/gitlab-org/gitlab-build-images:nanoc-bootstrap-ruby-2.4-alpine"
|
image: "registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-docs-lint"
|
||||||
stage: test
|
stage: test
|
||||||
cache: {}
|
cache: {}
|
||||||
dependencies: []
|
dependencies: []
|
||||||
|
@ -615,8 +614,8 @@ docs lint:
|
||||||
script:
|
script:
|
||||||
- scripts/lint-doc.sh
|
- scripts/lint-doc.sh
|
||||||
- scripts/lint-changelog-yaml
|
- scripts/lint-changelog-yaml
|
||||||
- mv doc/ /nanoc/content/
|
- mv doc/ /tmp/gitlab-docs/content/
|
||||||
- cd /nanoc
|
- cd /tmp/gitlab-docs
|
||||||
# Build HTML from Markdown
|
# Build HTML from Markdown
|
||||||
- bundle exec nanoc
|
- bundle exec nanoc
|
||||||
# Check the internal links
|
# Check the internal links
|
||||||
|
@ -729,6 +728,9 @@ karma:
|
||||||
dependencies:
|
dependencies:
|
||||||
- compile-assets
|
- compile-assets
|
||||||
- setup-test-env
|
- setup-test-env
|
||||||
|
variables:
|
||||||
|
# we override the max_old_space_size to prevent OOM errors
|
||||||
|
NODE_OPTIONS: --max_old_space_size=3584
|
||||||
script:
|
script:
|
||||||
- export BABEL_ENV=coverage CHROME_LOG_FILE=chrome_debug.log
|
- export BABEL_ENV=coverage CHROME_LOG_FILE=chrome_debug.log
|
||||||
- date
|
- date
|
||||||
|
@ -743,6 +745,8 @@ karma:
|
||||||
paths:
|
paths:
|
||||||
- chrome_debug.log
|
- chrome_debug.log
|
||||||
- coverage-javascript/
|
- coverage-javascript/
|
||||||
|
reports:
|
||||||
|
junit: junit_karma.xml
|
||||||
|
|
||||||
code_quality:
|
code_quality:
|
||||||
<<: *dedicated-no-docs-no-db-pull-cache-job
|
<<: *dedicated-no-docs-no-db-pull-cache-job
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
/doc/ @axil @marcia
|
/doc/ @axil @marcia
|
||||||
|
|
||||||
# Frontend maintainers should see everything in `app/assets/`
|
# Frontend maintainers should see everything in `app/assets/`
|
||||||
app/assets/ @annabeldunstone @ClemMakesApps @fatihacet @filipa @iamphill @mikegreiling @timzallmann
|
app/assets/ @ClemMakesApps @fatihacet @filipa @iamphill @mikegreiling @timzallmann
|
||||||
|
*.scss @annabeldunstone @ClemMakesApps @fatihacet @filipa @iamphill @mikegreiling @timzallmann
|
||||||
|
|
||||||
# Someone from the database team should review changes in `db/`
|
# Someone from the database team should review changes in `db/`
|
||||||
db/ @abrandl @NikolayS
|
db/ @abrandl @NikolayS
|
||||||
|
@ -15,3 +16,5 @@ db/ @abrandl @NikolayS
|
||||||
/ee/lib/gitlab/code_owners/ @reprazent
|
/ee/lib/gitlab/code_owners/ @reprazent
|
||||||
/ee/lib/ee/gitlab/auth/ldap/ @dblessing @mkozono
|
/ee/lib/ee/gitlab/auth/ldap/ @dblessing @mkozono
|
||||||
/lib/gitlab/auth/ldap/ @dblessing @mkozono
|
/lib/gitlab/auth/ldap/ @dblessing @mkozono
|
||||||
|
/lib/gitlab/ci/templates/ @nolith @zj
|
||||||
|
/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml @DylanGriffith @mayra-cabrera @tkuah
|
||||||
|
|
21
.rubocop.yml
|
@ -35,6 +35,25 @@ Style/MutableConstant:
|
||||||
Style/SafeNavigation:
|
Style/SafeNavigation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
# Frozen String Literal
|
||||||
|
Style/FrozenStringLiteralComment:
|
||||||
|
Enabled: true
|
||||||
|
Exclude:
|
||||||
|
- 'config.ru'
|
||||||
|
- 'Dangerfile'
|
||||||
|
- 'Gemfile'
|
||||||
|
- 'Rakefile'
|
||||||
|
- 'app/views/**/*'
|
||||||
|
- 'config/**/*'
|
||||||
|
- 'danger/**/*'
|
||||||
|
- 'db/**/*'
|
||||||
|
- 'ee/**/*'
|
||||||
|
- 'lib/**/*'
|
||||||
|
- 'qa/**/*'
|
||||||
|
- 'rubocop/**/*'
|
||||||
|
- 'scripts/**/*'
|
||||||
|
- 'spec/**/*'
|
||||||
|
|
||||||
Naming/FileName:
|
Naming/FileName:
|
||||||
ExpectMatchingDefinition: true
|
ExpectMatchingDefinition: true
|
||||||
Exclude:
|
Exclude:
|
||||||
|
@ -111,7 +130,7 @@ Naming/FileName:
|
||||||
- XSRF
|
- XSRF
|
||||||
- XSS
|
- XSS
|
||||||
|
|
||||||
# Gitlab ###################################################################
|
# GitLab ###################################################################
|
||||||
|
|
||||||
Gitlab/ModuleWithInstanceVariables:
|
Gitlab/ModuleWithInstanceVariables:
|
||||||
Enable: true
|
Enable: true
|
||||||
|
|
|
@ -10,24 +10,6 @@
|
||||||
Capybara/CurrentPathExpectation:
|
Capybara/CurrentPathExpectation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 23
|
|
||||||
FactoryBot/DynamicAttributeDefinedStatically:
|
|
||||||
Exclude:
|
|
||||||
- 'spec/factories/broadcast_messages.rb'
|
|
||||||
- 'spec/factories/ci/builds.rb'
|
|
||||||
- 'spec/factories/ci/runners.rb'
|
|
||||||
- 'spec/factories/clusters/applications/helm.rb'
|
|
||||||
- 'spec/factories/clusters/platforms/kubernetes.rb'
|
|
||||||
- 'spec/factories/emails.rb'
|
|
||||||
- 'spec/factories/gpg_keys.rb'
|
|
||||||
- 'spec/factories/group_members.rb'
|
|
||||||
- 'spec/factories/merge_requests.rb'
|
|
||||||
- 'spec/factories/notes.rb'
|
|
||||||
- 'spec/factories/oauth_access_grants.rb'
|
|
||||||
- 'spec/factories/project_members.rb'
|
|
||||||
- 'spec/factories/todos.rb'
|
|
||||||
- 'spec/factories/uploads.rb'
|
|
||||||
|
|
||||||
# Offense count: 167
|
# Offense count: 167
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Layout/EmptyLinesAroundArguments:
|
Layout/EmptyLinesAroundArguments:
|
||||||
|
@ -53,20 +35,6 @@ Layout/IndentArray:
|
||||||
Layout/IndentHash:
|
Layout/IndentHash:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 11
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: AllowForAlignment.
|
|
||||||
Layout/SpaceBeforeFirstArg:
|
|
||||||
Exclude:
|
|
||||||
- 'config/routes/project.rb'
|
|
||||||
- 'db/migrate/20170506185517_add_foreign_key_pipeline_schedules_and_pipelines.rb'
|
|
||||||
- 'features/steps/project/source/browse_files.rb'
|
|
||||||
- 'features/steps/project/source/markdown_render.rb'
|
|
||||||
- 'lib/api/runners.rb'
|
|
||||||
- 'spec/features/search/user_uses_search_filters_spec.rb'
|
|
||||||
- 'spec/routing/project_routing_spec.rb'
|
|
||||||
- 'spec/services/system_note_service_spec.rb'
|
|
||||||
|
|
||||||
# Offense count: 93
|
# Offense count: 93
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: EnforcedStyle.
|
# Configuration parameters: EnforcedStyle.
|
||||||
|
@ -74,15 +42,6 @@ Layout/SpaceBeforeFirstArg:
|
||||||
Layout/SpaceInLambdaLiteral:
|
Layout/SpaceInLambdaLiteral:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 1
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets.
|
|
||||||
# SupportedStyles: space, no_space, compact
|
|
||||||
# SupportedStylesForEmptyBrackets: space, no_space
|
|
||||||
Layout/SpaceInsideArrayLiteralBrackets:
|
|
||||||
Exclude:
|
|
||||||
- 'spec/lib/gitlab/import_export/relation_factory_spec.rb'
|
|
||||||
|
|
||||||
# Offense count: 327
|
# Offense count: 327
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
|
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
|
||||||
|
@ -96,14 +55,6 @@ Layout/SpaceInsideBlockBraces:
|
||||||
Layout/SpaceInsideParens:
|
Layout/SpaceInsideParens:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 14
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Layout/SpaceInsidePercentLiteralDelimiters:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/gitlab/git_access.rb'
|
|
||||||
- 'lib/gitlab/health_checks/fs_shards_check.rb'
|
|
||||||
- 'spec/lib/gitlab/health_checks/fs_shards_check_spec.rb'
|
|
||||||
|
|
||||||
# Offense count: 26
|
# Offense count: 26
|
||||||
Lint/DuplicateMethods:
|
Lint/DuplicateMethods:
|
||||||
Exclude:
|
Exclude:
|
||||||
|
@ -135,31 +86,11 @@ Lint/InterpolationCheck:
|
||||||
Lint/MissingCopEnableDirective:
|
Lint/MissingCopEnableDirective:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 2
|
|
||||||
Lint/NestedPercentLiteral:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/gitlab/git/repository.rb'
|
|
||||||
- 'spec/support/shared_examples/email_format_shared_examples.rb'
|
|
||||||
|
|
||||||
# Offense count: 1
|
# Offense count: 1
|
||||||
Lint/ReturnInVoidContext:
|
Lint/ReturnInVoidContext:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/models/project.rb'
|
- 'app/models/project.rb'
|
||||||
|
|
||||||
# Offense count: 1
|
|
||||||
# Configuration parameters: IgnoreImplicitReferences.
|
|
||||||
Lint/ShadowedArgument:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/gitlab/database/sha_attribute.rb'
|
|
||||||
|
|
||||||
# Offense count: 3
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Lint/UnneededRequireStatement:
|
|
||||||
Exclude:
|
|
||||||
- 'db/post_migrate/20161221153951_rename_reserved_project_names.rb'
|
|
||||||
- 'db/post_migrate/20170313133418_rename_more_reserved_project_names.rb'
|
|
||||||
- 'lib/declarative_policy.rb'
|
|
||||||
|
|
||||||
# Offense count: 9
|
# Offense count: 9
|
||||||
Lint/UriEscapeUnescape:
|
Lint/UriEscapeUnescape:
|
||||||
Exclude:
|
Exclude:
|
||||||
|
@ -199,16 +130,6 @@ Naming/HeredocDelimiterCase:
|
||||||
Naming/HeredocDelimiterNaming:
|
Naming/HeredocDelimiterNaming:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 1
|
|
||||||
Performance/UnfreezeString:
|
|
||||||
Exclude:
|
|
||||||
- 'features/steps/project/commits/commits.rb'
|
|
||||||
|
|
||||||
# Offense count: 1
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Performance/UriDefaultParser:
|
|
||||||
Exclude:
|
|
||||||
- 'lib/gitlab/url_sanitizer.rb'
|
|
||||||
|
|
||||||
# Offense count: 3821
|
# Offense count: 3821
|
||||||
# Configuration parameters: Prefixes.
|
# Configuration parameters: Prefixes.
|
||||||
|
@ -445,7 +366,6 @@ Style/Dir:
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/EachWithObject:
|
Style/EachWithObject:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'config/initializers/gollum.rb'
|
|
||||||
- 'lib/expand_variables.rb'
|
- 'lib/expand_variables.rb'
|
||||||
- 'lib/gitlab/ci/ansi2html.rb'
|
- 'lib/gitlab/ci/ansi2html.rb'
|
||||||
- 'lib/gitlab/ee_compat_check.rb'
|
- 'lib/gitlab/ee_compat_check.rb'
|
||||||
|
@ -808,20 +728,6 @@ Style/UnlessElse:
|
||||||
Style/UnneededInterpolation:
|
Style/UnneededInterpolation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 11
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Style/ZeroLengthPredicate:
|
|
||||||
Exclude:
|
|
||||||
- 'app/models/deploy_key.rb'
|
|
||||||
- 'app/models/network/commit.rb'
|
|
||||||
- 'app/models/network/graph.rb'
|
|
||||||
- 'app/models/project_services/asana_service.rb'
|
|
||||||
- 'app/services/boards/create_service.rb'
|
|
||||||
- 'app/services/merge_requests/conflicts/list_service.rb'
|
|
||||||
- 'lib/declarative_policy/dsl.rb'
|
|
||||||
- 'lib/extracts_path.rb'
|
|
||||||
- 'lib/gitlab/git/repository.rb'
|
|
||||||
|
|
||||||
# Offense count: 22840
|
# Offense count: 22840
|
||||||
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
||||||
# URISchemes: http, https
|
# URISchemes: http, https
|
||||||
|
|
350
CHANGELOG.md
|
@ -2,94 +2,322 @@
|
||||||
documentation](doc/development/changelog.md) for instructions on adding your own
|
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||||
entry.
|
entry.
|
||||||
|
|
||||||
## 11.3.11 (2018-11-26)
|
## 11.4.9 (2018-12-03)
|
||||||
|
|
||||||
### Security (33 changes)
|
### Fixed (2 changes)
|
||||||
|
|
||||||
- Filter user sensitive data from discussions JSON. !2537
|
- Display impersonation token value only after creation. !22916
|
||||||
- Escape entity title while autocomplete template rendering to prevent XSS. !2557
|
- Correctly handle data-loss scenarios when encrypting columns. !23306
|
||||||
- Restrict Personal Access Tokens to API scope on web requests.
|
|
||||||
|
|
||||||
|
## 11.4.8 (2018-11-27)
|
||||||
|
|
||||||
|
### Security (24 changes)
|
||||||
|
|
||||||
|
- Escape entity title while autocomplete template rendering to prevent XSS. !2571
|
||||||
|
- Resolve reflected XSS in Ouath authorize window.
|
||||||
- Fix XSS in merge request source branch name.
|
- Fix XSS in merge request source branch name.
|
||||||
- Escape user fullname while rendering autocomplete template to prevent XSS.
|
- Escape user fullname while rendering autocomplete template to prevent XSS.
|
||||||
- Fix CRLF vulnerability in Project hooks.
|
- Fix CRLF vulnerability in Project hooks.
|
||||||
- Fix possible XSS attack in Markdown urls with spaces.
|
- Fix possible XSS attack in Markdown urls with spaces.
|
||||||
- Redact sensitive information on gitlab-workhorse log.
|
- Redact sensitive information on gitlab-workhorse log.
|
||||||
- Set timeout for syntax highlighting.
|
|
||||||
- Do not follow redirects in Prometheus service when making http requests to the configured api url.
|
- Do not follow redirects in Prometheus service when making http requests to the configured api url.
|
||||||
- Persist only SHA digest of PersonalAccessToken#token.
|
- Persist only SHA digest of PersonalAccessToken#token.
|
||||||
- Sanitize JSON data properly to fix XSS on Issue details page.
|
|
||||||
- Don't expose confidential information in commit message list.
|
- Don't expose confidential information in commit message list.
|
||||||
- Markdown API no longer displays confidential title references unless authorized.
|
|
||||||
- Provide email notification when a user changes their email address.
|
- Provide email notification when a user changes their email address.
|
||||||
- Properly filter private references from system notes.
|
- Restrict Personal Access Tokens to API scope on web requests.
|
||||||
- Redact personal tokens in unsubscribe links.
|
- Redact personal tokens in unsubscribe links.
|
||||||
- Resolve reflected XSS in Ouath authorize window.
|
|
||||||
- Fix SSRF in project integrations.
|
- Fix SSRF in project integrations.
|
||||||
- Fix stored XSS in merge requests from imported repository.
|
|
||||||
- Fixed ability to comment on locked/confidential issues.
|
- Fixed ability to comment on locked/confidential issues.
|
||||||
- Fixed ability of guest users to edit/delete comments on locked or confidential issues.
|
- Fixed ability of guest users to edit/delete comments on locked or confidential issues.
|
||||||
- Fix milestone promotion authorization check.
|
- Fix milestone promotion authorization check.
|
||||||
- Monkey kubeclient to not follow any redirects.
|
- Monkey kubeclient to not follow any redirects.
|
||||||
- Configure mermaid to not render HTML content in diagrams.
|
- Configure mermaid to not render HTML content in diagrams.
|
||||||
- Redact confidential events in the API.
|
|
||||||
- Fix xss vulnerability sourced from package.json.
|
|
||||||
- Fix a possible symlink time of check to time of use race condition in GitLab Pages.
|
- Fix a possible symlink time of check to time of use race condition in GitLab Pages.
|
||||||
- Removed ability to see private group names when the group id is entered in the url.
|
- Removed ability to see private group names when the group id is entered in the url.
|
||||||
- Fix stored XSS for Environments.
|
- Fix stored XSS for Environments.
|
||||||
- Block loopback addresses in UrlBlocker.
|
|
||||||
- Prevent SSRF attacks in HipChat integration.
|
- Prevent SSRF attacks in HipChat integration.
|
||||||
- Validate Wiki attachments are valid temporary files.
|
- Validate Wiki attachments are valid temporary files.
|
||||||
|
|
||||||
|
|
||||||
## 11.3.10 (2018-11-18)
|
## 11.4.7 (2018-11-20)
|
||||||
|
|
||||||
|
- No changes.
|
||||||
|
|
||||||
|
## 11.4.6 (2018-11-18)
|
||||||
|
|
||||||
### Security (1 change)
|
### Security (1 change)
|
||||||
|
|
||||||
- Escape user fullname while rendering autocomplete template to prevent XSS.
|
- Escape user fullname while rendering autocomplete template to prevent XSS.
|
||||||
|
|
||||||
|
|
||||||
## 11.3.9 (2018-10-31)
|
## 11.4.5 (2018-11-04)
|
||||||
|
|
||||||
|
### Fixed (4 changes, 1 of them is from the community)
|
||||||
|
|
||||||
|
- fix link to enable usage ping from convdev index. !22545 (Anand Capur)
|
||||||
|
- Update gitlab-ui dependency to 1.8.0-hotfix.1 to fix IE11 bug.
|
||||||
|
- Remove duplicate escape in job sidebar.
|
||||||
|
- Fixed merge request fill tree toggling not respecting fluid width preference.
|
||||||
|
|
||||||
|
### Other (1 change)
|
||||||
|
|
||||||
|
- Fix stage dropdown not rendering in different languages.
|
||||||
|
|
||||||
|
|
||||||
|
## 11.4.4 (2018-10-30)
|
||||||
|
|
||||||
### Security (1 change)
|
### Security (1 change)
|
||||||
|
|
||||||
- Monkey kubeclient to not follow any redirects.
|
- Monkey kubeclient to not follow any redirects.
|
||||||
|
|
||||||
|
|
||||||
## 11.3.8 (2018-10-27)
|
## 11.4.3 (2018-10-26)
|
||||||
|
|
||||||
- No changes.
|
- No changes.
|
||||||
|
|
||||||
## 11.3.7 (2018-10-26)
|
## 11.4.2 (2018-10-25)
|
||||||
|
|
||||||
### Security (6 changes)
|
### Security (5 changes)
|
||||||
|
|
||||||
- Escape entity title while autocomplete template rendering to prevent XSS. !2557
|
- Escape entity title while autocomplete template rendering to prevent XSS. !2571
|
||||||
- Persist only SHA digest of PersonalAccessToken#token.
|
- Persist only SHA digest of PersonalAccessToken#token.
|
||||||
- Fix XSS in merge request source branch name.
|
|
||||||
- Redact personal tokens in unsubscribe links.
|
- Redact personal tokens in unsubscribe links.
|
||||||
- Prevent SSRF attacks in HipChat integration.
|
- Block loopback addresses in UrlBlocker.
|
||||||
- Validate Wiki attachments are valid temporary files.
|
- Validate Wiki attachments are valid temporary files.
|
||||||
|
|
||||||
|
|
||||||
## 11.3.6 (2018-10-17)
|
## 11.4.1 (2018-10-23)
|
||||||
|
|
||||||
- No changes.
|
### Security (2 changes)
|
||||||
|
|
||||||
## 11.3.5 (2018-10-15)
|
- Fix XSS in merge request source branch name.
|
||||||
|
- Prevent SSRF attacks in HipChat integration.
|
||||||
### Fixed (2 changes)
|
|
||||||
|
|
||||||
- Fix loading issue on some merge request discussion. !21982
|
|
||||||
- Fix project deletion when there is a export available. !22276
|
|
||||||
|
|
||||||
|
|
||||||
## 11.3.4 (2018-10-05)
|
## 11.4.0 (2018-10-22)
|
||||||
|
|
||||||
### Security (3 changes)
|
### Security (9 changes)
|
||||||
|
|
||||||
- Filter user sensitive data from discussions JSON. !2537
|
- Filter user sensitive data from discussions JSON. !2536
|
||||||
- Properly filter private references from system notes.
|
- Encrypt webhook tokens and URLs in the database. !21645
|
||||||
|
- Redact confidential events in the API.
|
||||||
|
- Set timeout for syntax highlighting.
|
||||||
|
- Sanitize JSON data properly to fix XSS on Issue details page.
|
||||||
- Markdown API no longer displays confidential title references unless authorized.
|
- Markdown API no longer displays confidential title references unless authorized.
|
||||||
|
- Properly filter private references from system notes.
|
||||||
|
- Fix stored XSS in merge requests from imported repository.
|
||||||
|
- Fix xss vulnerability sourced from package.json.
|
||||||
|
|
||||||
|
### Removed (2 changes)
|
||||||
|
|
||||||
|
- Remove background job throttling feature. !21748
|
||||||
|
- Remove sidekiq info from performance bar.
|
||||||
|
|
||||||
|
### Fixed (68 changes, 18 of them are from the community)
|
||||||
|
|
||||||
|
- Fixes 500 for cherry pick API with empty branch name. !21501 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Fix sorting by priority or popularity on group issues page, when also searching issue content. !21521
|
||||||
|
- Fix vertical alignment of text in diffs. !21573
|
||||||
|
- Fix performance bar modal position. !21577
|
||||||
|
- Bump KaTeX version to 0.9.0. !21625
|
||||||
|
- Correctly show legacy diff notes in the merge request changes tab. !21652
|
||||||
|
- Synchronize the default branch when updating a remote mirror. !21653
|
||||||
|
- Filter group milestones based on user membership. !21660
|
||||||
|
- Fix double title in merge request chat messages. !21670 (Kukovskii Vladimir)
|
||||||
|
- Delete container repository tags outside of transaction. !21679
|
||||||
|
- Images are no longer displayed in Todo descriptions. !21704
|
||||||
|
- Fixed merge request widget discussion state not updating after resolving discussions. !21705
|
||||||
|
- Vendor Auto-DevOps.gitlab-ci.yml to fix bug where the deploy job does not wait for Deployment to complete. !21713
|
||||||
|
- Use Reliable Sidekiq fetch. !21715
|
||||||
|
- No longer show open issues from archived projects in group issue board. !21721
|
||||||
|
- Issue and MR count now ignores archived projects. !21721
|
||||||
|
- Fix resizing of monitoring dashboard. !21730
|
||||||
|
- Fix object storage uploads not working with AWS v2. !21731
|
||||||
|
- Don't ignore first action when assign and unassign quick actions are used in the same comment. !21749
|
||||||
|
- Align form labels following Bootstrap 4 docs. !21752
|
||||||
|
- Respect the user commit email in more places. !21773
|
||||||
|
- Use stats RPC when comparing diffs. !21778
|
||||||
|
- Show commit details for selected commit in MR diffs. !21784
|
||||||
|
- Resolve "Geo: Does not mark repositories as missing on primary due to stale cache". !21789
|
||||||
|
- Fix leading slash in redirects and add rubocop cop. !21828 (Sanad Liaquat)
|
||||||
|
- Fix activity titles for MRs in chat notification services. !21834
|
||||||
|
- Hides Close Merge request btn on merged Merge request. !21840 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Doesn't synchronize the default branch for push mirrors. !21861
|
||||||
|
- Fix broken styling when issue board is collapsed. !21868 (Andrea Leone)
|
||||||
|
- Set a header for custom error pages to prevent them from being intercepted by gitlab-workhorse. !21870 (David Piegza)
|
||||||
|
- Fix resolved discussions being unresolved when commented on. !21881
|
||||||
|
- Fix timeout when running the RemoveRestrictedTodos background migration. !21893
|
||||||
|
- Enable the ability to use the force env for rebuilding authorized_keys during a restore. !21896
|
||||||
|
- Fix link handling for issue cards to avoid too sensitive drag events. !21910 (Johann Hubert Sonntagbauer)
|
||||||
|
- Guard against a login attempt with invalid CSRF token. !21934
|
||||||
|
- Allow setting user's organization and location attributes through the API by adding them to the list of allowed parameters. !21938 (Alexis Reigel)
|
||||||
|
- Includes commit stats in POST project commits API. !21968 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Fix loading issue on some merge request discussion. !21982
|
||||||
|
- Prevent Error 500s with invalid relative links. !22001
|
||||||
|
- Fix stale issue boards after browser back. !22006 (Johann Hubert Sonntagbauer)
|
||||||
|
- Filter issues without an Assignee via the API. !22009 (Eva Kadlecová)
|
||||||
|
- Fixes modal button alignment. !22024 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Fix rendering placeholder notes. !22078
|
||||||
|
- Instance Configuration page now displays correct SSH fingerprints. !22081
|
||||||
|
- Fix showing diff file header for renamed files. !22089
|
||||||
|
- Fix LFS uploaded images not being rendered. !22092
|
||||||
|
- Fix the issue where long environment names aren't being truncated, causing the environment name to overlap into the column next to it. !22104
|
||||||
|
- Trim whitespace when inviting a new user by email. !22119 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Fix incorrect parent path on group settings page. !22142
|
||||||
|
- Update copy to clipboard button data for application secret. !22268 (George Tsiolis)
|
||||||
|
- Improve MR file tree in smaller screens. !22273
|
||||||
|
- Fix project deletion when there is a export available. !22276
|
||||||
|
- Fixes stuck block URL linking to documentation instead of settings page. !22286
|
||||||
|
- Fix caching issue with pipelines URL. !22293
|
||||||
|
- Fix erased block not being rendered when job was erased. !22294
|
||||||
|
- Load correct stage in the stages dropdown. !22317
|
||||||
|
- Fixes close/reopen quick actions preview for issues and merge_requests. !22343 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Allow Issue and Merge Request sidebar to be toggled from collapsed state. !22353
|
||||||
|
- Fix filter bar height bug when a tag is added.
|
||||||
|
- Fix the state of the Done button when there is an error in the GitLab Todos section. (marcos8896)
|
||||||
|
- Fix wrong text color of help text in merge request creation. (Gerard Montemayor)
|
||||||
|
- Add borders and white background to markdown tables.
|
||||||
|
- Fixed mention autocomplete in edit merge request.
|
||||||
|
- Fix long webhook URL overflow for custom integration. (Kukovskii Vladimir)
|
||||||
|
- Fixed file templates not fully being fetched in Web IDE.
|
||||||
|
- Fixes performance bar looking for a key in a undefined prop.
|
||||||
|
- Hides sidebar for job page in mobile.
|
||||||
|
- Fixes triggered/created labeled in job header.
|
||||||
|
|
||||||
|
### Changed (26 changes, 4 of them are from the community)
|
||||||
|
|
||||||
|
- Enable unauthenticated access to public SSH keys via the API. !20118 (Ronald Claveau)
|
||||||
|
- Support Kubernetes RBAC for GitLab Managed Apps when creating new clusters. !21401
|
||||||
|
- Highlight current user in comments. !21406
|
||||||
|
- Excludes project marked from deletion to projects API. !21542 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Improve install flow of Kubernetes cluster apps. !21567
|
||||||
|
- Move including external files in .gitlab-ci.yml from Starter to Libre. !21603
|
||||||
|
- Simplify runner registration token resetting. !21658
|
||||||
|
- Filter any parameters ending with "key" in logs. !21688
|
||||||
|
- Ensure the schema is loaded with post_migrations included. !21689
|
||||||
|
- Updated icons used in filtered search dropdowns. !21694
|
||||||
|
- Enable omniauth by default. !21700
|
||||||
|
- Vendor Auto-DevOps.gitlab-ci.yml to refactor registry_login. !21714 (Laurent Goderre @LaurentGoderre)
|
||||||
|
- Add Gitaly diff stats RPC client. !21732
|
||||||
|
- Allow user to revoke an authorized application even if User OAuth applications setting is disabled in admin settings. !21835
|
||||||
|
- Change vertical margin of page titles to 16px. !21888
|
||||||
|
- Preserve order of project tags list. !21897
|
||||||
|
- Avoid close icon leaving the modal header. !21904
|
||||||
|
- Allow /copy_metadata for new issues and MRs. !21953
|
||||||
|
- Link to the tag for a version on the help page instead of to the commit. !22015
|
||||||
|
- Show SHA for pre-release versions on the help page. !22026
|
||||||
|
- Use local tiller for Auto DevOps. !22036
|
||||||
|
- Remove 'rbac_clusters' feature flag. !22096
|
||||||
|
- Increased retained event data by extending events pruner timeframe to 2 years. !22145
|
||||||
|
- Add installation type to backup information file. !22150
|
||||||
|
- Remove duplicate button from the markdown header toolbar. !22192 (George Tsiolis)
|
||||||
|
- Update to Rouge 3.3.0 including frozen string literals for improved memory usage.
|
||||||
|
|
||||||
|
### Performance (17 changes, 6 of them are from the community)
|
||||||
|
|
||||||
|
- Enable frozen string in app/controllers/**/*.rb.
|
||||||
|
- Improve lazy image loading performance by using IntersectionObserver where available. !21565
|
||||||
|
- Adds support for Gitaly ListLastCommitsForTree RPC in order to make bulk-fetch of commits more performant. !21921
|
||||||
|
- Dont create license_management build when not included in license. !21958
|
||||||
|
- Skip creating auto devops jobs for sast, container_scanning, dast, dependency_scanning when not licensed. !21959
|
||||||
|
- Reduce queries needed to compute notification recipients. !22050
|
||||||
|
- Banzai label ref finder - minimize SQL calls by sharing context more aggresively. !22070
|
||||||
|
- Removes expensive dead code on main MR page request. !22153
|
||||||
|
- Lazy load xterm custom colors css.
|
||||||
|
- Mitigate N+1 queries when parsing commit references in comments.
|
||||||
|
- Enable more frozen string in app/controllers/. (gfyoung)
|
||||||
|
- Increase performance when creating discussions on diff.
|
||||||
|
- Enable frozen string in lib/api and lib/backup. (gfyoung)
|
||||||
|
- Enable frozen string in vestigial files. (gfyoung)
|
||||||
|
- Enable frozen string for app/helpers/**/*.rb. (gfyoung)
|
||||||
|
- Enable frozen string in app/graphql + app/finders. (gfyoung)
|
||||||
|
- Enable even more frozen string in app/controllers. (gfyoung)
|
||||||
|
|
||||||
|
### Added (37 changes, 21 of them are from the community)
|
||||||
|
|
||||||
|
- Allow file templates to be requested at the project level. !7776
|
||||||
|
- Add /lock and /unlock quick actions. !15197 (Mehdi Lahmam (@mehlah))
|
||||||
|
- Added search functionality for Work In Progress (WIP) merge requests. !18119 (Chantal Rollison)
|
||||||
|
- pipeline webhook event now contain pipeline variables. !18171 (Pierre Tardy)
|
||||||
|
- Add markdown header toolbar button to insert table. !18480 (George Tsiolis)
|
||||||
|
- Add link button to markdown editor toolbar. !18579 (Jan Beckmann)
|
||||||
|
- Add access control to GitLab pages and make it possible to enable/disable it in project settings. !18589 (Tuomo Ala-Vannesluoma)
|
||||||
|
- Add a filter bar to the admin runners view and add a state filter. !19625 (Alexis Reigel)
|
||||||
|
- Add a type filter to the admin runners view. !19649 (Alexis Reigel)
|
||||||
|
- Allow user to choose the email used for commits made through GitLab's UI. !21213 (Joshua Campbell)
|
||||||
|
- Add autocomplete drop down filter for project snippets. !21458 (Fabian Schneider)
|
||||||
|
- Allow events filter to be set in the URL in addition to cookie. !21557 (Igor @igas)
|
||||||
|
- Adds a initialize_with_readme parameter to POST /projects. !21617 (Steve)
|
||||||
|
- Add ability to skip user email confirmation with API. !21630
|
||||||
|
- Add sorting for labels on labels page. !21642
|
||||||
|
- Set user status from within user menu. !21643
|
||||||
|
- Copy nurtch demo notebooks at Jupyter startup. !21698 (Amit Rathi)
|
||||||
|
- Allows to sort projects by most stars. !21762 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Allow pipelines to schedule delayed job runs. !21767
|
||||||
|
- Added tree of changed files to merge request diffs. !21833
|
||||||
|
- Add GitLab version components to CI environment variables. !21853
|
||||||
|
- Allows to chmod file with commits API. !21866 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Make single diff patch limit configurable. !21886
|
||||||
|
- Extend reports feature to support Security Products. !21892
|
||||||
|
- Adds the user's public_email attribute to the API. !21909 (Alexis Reigel)
|
||||||
|
- Update all gitlab CI templates from gitlab-org/gitlab-ci-yml. !21929
|
||||||
|
- Add support for setting the public email through the api. !21938 (Alexis Reigel)
|
||||||
|
- Support db migration and initialization for Auto DevOps. !21955
|
||||||
|
- Add subscribe filter to group and project labels pages. !21965
|
||||||
|
- Add support for pipeline only/except policy for modified paths. !21981
|
||||||
|
- Docs for Project/Groups members API with inherited members. !21984 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Adds Web IDE commits to usage ping. !22007
|
||||||
|
- Add timed incremental rollout to Auto DevOps. !22023
|
||||||
|
- Show percentage of language detection on the language bar. !22056 (Johann Hubert Sonntagbauer)
|
||||||
|
- Allows to filter issues by Any milestone in the API. !22080 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Add button to download 2FA codes. (Luke Picciau)
|
||||||
|
- Render log artifact files in GitLab.
|
||||||
|
|
||||||
|
### Other (42 changes, 16 of them are from the community)
|
||||||
|
|
||||||
|
- Send deployment information in job API. !21307
|
||||||
|
- Split admin settings into multiple sub pages. !21467
|
||||||
|
- Remove Rugged and shell code from Gitlab::Git. !21488
|
||||||
|
- Add trigger information in job API. !21495
|
||||||
|
- Add empty state illustration information in job API. !21532
|
||||||
|
- Add retried jobs to pipeline stage. !21558
|
||||||
|
- Rails 5: fix issue move service In rails 5, the attributes method for an enum returns the name instead of the database integer. !21616 (Jasper Maes)
|
||||||
|
- Expose project runners in job API. !21618
|
||||||
|
- create from template: hide checkbox for initializing repository with readme. !21646
|
||||||
|
- Adds new 'Overview' tab on user profile page. !21663
|
||||||
|
- Add clean-up phase for ScheduleDiffFilesDeletion migration. !21734
|
||||||
|
- Prevents private profile help link from toggling checkbox. !21757
|
||||||
|
- Make AutoDevOps work behind proxy. !21775 (Sergej - @kinolaev)
|
||||||
|
- Use Vue components and new API to render Artifacts, Trigger Variables and Commit blocks on Job page. !21777
|
||||||
|
- Add wrapper rake task to migrate all uploads to OS. !21779
|
||||||
|
- Retroactively fill pipeline source for external pipelines. !21814
|
||||||
|
- Rename squash before merge vue component. !21851 (George Tsiolis)
|
||||||
|
- Fix merge request header margins. !21878
|
||||||
|
- Fix committer typo. !21899 (George Tsiolis)
|
||||||
|
- Adds an extra width to the responsive tables. !21928
|
||||||
|
- Expose has_trace in job API. !21950
|
||||||
|
- Rename block scope local variable in table pagination spec. !21969 (George Tsiolis)
|
||||||
|
- Fix blue, orange, and red color inconsistencies. !21972
|
||||||
|
- Update operations metrics empty state. !21974 (George Tsiolis)
|
||||||
|
- Improve empty project placeholder for non-members and members without write access. !21977 (George Tsiolis)
|
||||||
|
- Add copy to clipboard button for application id and secret. !21978 (George Tsiolis)
|
||||||
|
- Add link component to UserAvatarLink component. !21986 (George Tsiolis)
|
||||||
|
- Add link component to DownloadViewer component. !21987 (George Tsiolis)
|
||||||
|
- Rephrase 2FA and TOTP documentation and view. !21998 (Marc Schwede)
|
||||||
|
- Update project path on project name autofill. !22016
|
||||||
|
- Improve logging when username update fails due to registry tags. !22038
|
||||||
|
- Align collapsed sidebar avatar container. !22044 (George Tsiolis)
|
||||||
|
- Rails5: fix artifacts controller download spec Rails5 has params[:file_type] as '' if file_type is included as nil in the request. !22123 (Jasper Maes)
|
||||||
|
- Hide pagination for personal projects on profile overview tab. !22321
|
||||||
|
- Extracts scroll position check into reusable functions.
|
||||||
|
- Uses Vuex store in job details page and removes old mediator pattern.
|
||||||
|
- Render 412 when invalid UTF-8 parameters are passed to controller.
|
||||||
|
- Renders Job show page in new Vue app.
|
||||||
|
- Add link to User Snippets in breadcrumbs of New User Snippet page. (J.D. Bean)
|
||||||
|
- Log project services errors when executing async.
|
||||||
|
- Update docs regarding frozen string. (gfyoung)
|
||||||
|
- Check frozen string in style builds. (gfyoung)
|
||||||
|
|
||||||
|
|
||||||
## 11.3.3 (2018-10-04)
|
## 11.3.3 (2018-10-04)
|
||||||
|
@ -369,6 +597,27 @@ entry.
|
||||||
- Creates Vue component for artifacts block on job page.
|
- Creates Vue component for artifacts block on job page.
|
||||||
|
|
||||||
|
|
||||||
|
## 11.2.5 (2018-10-05)
|
||||||
|
|
||||||
|
### Security (3 changes)
|
||||||
|
|
||||||
|
- Filter user sensitive data from discussions JSON. !2538
|
||||||
|
- Properly filter private references from system notes.
|
||||||
|
- Markdown API no longer displays confidential title references unless authorized.
|
||||||
|
|
||||||
|
|
||||||
|
## 11.2.4 (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.2.3 (2018-08-28)
|
## 11.2.3 (2018-08-28)
|
||||||
|
|
||||||
### Fixed (1 change)
|
### Fixed (1 change)
|
||||||
|
@ -636,6 +885,27 @@ entry.
|
||||||
- Moves help_popover component to a common location.
|
- Moves help_popover component to a common location.
|
||||||
|
|
||||||
|
|
||||||
|
## 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)
|
## 11.1.6 (2018-08-28)
|
||||||
|
|
||||||
### Fixed (1 change)
|
### Fixed (1 change)
|
||||||
|
@ -1246,7 +1516,7 @@ entry.
|
||||||
- Use the default strings of timeago.js for timeago. !19350 (Takuya Noguchi)
|
- Use the default strings of timeago.js for timeago. !19350 (Takuya Noguchi)
|
||||||
- Update selenium-webdriver to 3.12.0. !19351 (Takuya Noguchi)
|
- Update selenium-webdriver to 3.12.0. !19351 (Takuya Noguchi)
|
||||||
- Include username in output when testing SSH to GitLab. !19358
|
- Include username in output when testing SSH to GitLab. !19358
|
||||||
- Update screenshot in Gitlab.com integration documentation. !19433 (Tuğçe Nur Taş)
|
- Update screenshot in GitLab.com integration documentation. !19433 (Tuğçe Nur Taş)
|
||||||
- Users can accept terms during registration. !19583
|
- Users can accept terms during registration. !19583
|
||||||
- Fix issue count on sidebar.
|
- Fix issue count on sidebar.
|
||||||
- Add merge requests list endpoint for groups.
|
- Add merge requests list endpoint for groups.
|
||||||
|
@ -1376,7 +1646,7 @@ entry.
|
||||||
- Make toggle markdown preview shortcut only toggle selected field.
|
- Make toggle markdown preview shortcut only toggle selected field.
|
||||||
- Verifiy if pipeline has commit idetails and render information in MR widget when branch is deleted.
|
- Verifiy if pipeline has commit idetails and render information in MR widget when branch is deleted.
|
||||||
- Fixed inconsistent protected branch pill baseline.
|
- Fixed inconsistent protected branch pill baseline.
|
||||||
- Fix setting Gitlab metrics content types.
|
- Fix setting GitLab metrics content types.
|
||||||
- Display only generic message on merge error to avoid exposing any potentially sensitive or user unfriendly backend messages.
|
- Display only generic message on merge error to avoid exposing any potentially sensitive or user unfriendly backend messages.
|
||||||
- Fix label links update on project transfer.
|
- Fix label links update on project transfer.
|
||||||
- Breaks commit not found message in pipelines table.
|
- Breaks commit not found message in pipelines table.
|
||||||
|
@ -1746,7 +2016,7 @@ entry.
|
||||||
- Add 'Assigned Issues' and 'Assigned Merge Requests' as dashboard view choices for users. !17860 (Elias Werberich)
|
- Add 'Assigned Issues' and 'Assigned Merge Requests' as dashboard view choices for users. !17860 (Elias Werberich)
|
||||||
- Extend API for importing a project export with overwrite support. !17883
|
- Extend API for importing a project export with overwrite support. !17883
|
||||||
- Create Deploy Tokens to allow permanent access to repository and registry. !17894
|
- Create Deploy Tokens to allow permanent access to repository and registry. !17894
|
||||||
- Detect commit message trailers and link users properly to their accounts on Gitlab. !17919 (cousine)
|
- Detect commit message trailers and link users properly to their accounts on GitLab. !17919 (cousine)
|
||||||
- Adds cancel btn to new pages domain page. !18026 (Jacopo Beschi @jacopo-beschi)
|
- Adds cancel btn to new pages domain page. !18026 (Jacopo Beschi @jacopo-beschi)
|
||||||
- API: Add parameter merge_method to projects. !18031 (Jan Beckmann)
|
- API: Add parameter merge_method to projects. !18031 (Jan Beckmann)
|
||||||
- Introduce simpler env vars for auto devops REPLICAS and CANARY_REPLICAS #41436. !18036
|
- Introduce simpler env vars for auto devops REPLICAS and CANARY_REPLICAS #41436. !18036
|
||||||
|
@ -3194,7 +3464,7 @@ entry.
|
||||||
- [FIXED] Fix broken wiki pages that link to a wiki file. !15019
|
- [FIXED] Fix broken wiki pages that link to a wiki file. !15019
|
||||||
- [FIXED] Don't rename paths that were freed up when upgrading. !15029
|
- [FIXED] Don't rename paths that were freed up when upgrading. !15029
|
||||||
- [FIXED] Fix bitbucket login. !15051
|
- [FIXED] Fix bitbucket login. !15051
|
||||||
- [FIXED] Update gitaly in Gitlab 10.1 to 0.43.1 for temp file cleanup. !15055
|
- [FIXED] Update gitaly in GitLab 10.1 to 0.43.1 for temp file cleanup. !15055
|
||||||
- [FIXED] Use the correct visibility attribute for projects in system hooks. !15065
|
- [FIXED] Use the correct visibility attribute for projects in system hooks. !15065
|
||||||
- [FIXED] Normalize LDAP DN when looking up identity.
|
- [FIXED] Normalize LDAP DN when looking up identity.
|
||||||
- [FIXED] Adds callback functions for initial request in clusters page.
|
- [FIXED] Adds callback functions for initial request in clusters page.
|
||||||
|
@ -4904,7 +5174,7 @@ entry.
|
||||||
- Make user mentions case-insensitive. !10285 (blackst0ne)
|
- Make user mentions case-insensitive. !10285 (blackst0ne)
|
||||||
- Update rugged to 0.25.1.1. !10286 (Elan Ruusamäe)
|
- Update rugged to 0.25.1.1. !10286 (Elan Ruusamäe)
|
||||||
- Handle parsing OpenBSD ps output properly to display sidekiq infos on admin->monitoring->background. !10303 (Sebastian Reitenbach)
|
- Handle parsing OpenBSD ps output properly to display sidekiq infos on admin->monitoring->background. !10303 (Sebastian Reitenbach)
|
||||||
- Log errors during generating of Gitlab Pages to debug log. !10335 (Danilo Bargen)
|
- Log errors during generating of GitLab Pages to debug log. !10335 (Danilo Bargen)
|
||||||
- Update issue board cards design. !10353
|
- Update issue board cards design. !10353
|
||||||
- Tags can be protected, restricting creation of matching tags by user role. !10356
|
- Tags can be protected, restricting creation of matching tags by user role. !10356
|
||||||
- Set GIT_TERMINAL_PROMPT env variable in initializer. !10372
|
- Set GIT_TERMINAL_PROMPT env variable in initializer. !10372
|
||||||
|
@ -5317,7 +5587,7 @@ entry.
|
||||||
- Restore keyboard shortcuts for "Activity" and "Charts". !9680
|
- Restore keyboard shortcuts for "Activity" and "Charts". !9680
|
||||||
- Added commit array to Syshook json. !9685 (Gabriele Pongelli)
|
- Added commit array to Syshook json. !9685 (Gabriele Pongelli)
|
||||||
- Document ability to list issues with no labels using API. !9697 (Vignesh Ravichandran)
|
- Document ability to list issues with no labels using API. !9697 (Vignesh Ravichandran)
|
||||||
- Fix typo in Gitlab config file. !9702 (medied)
|
- Fix typo in GitLab config file. !9702 (medied)
|
||||||
- Fix json response in branches controller. !9710 (George Andrinopoulos)
|
- Fix json response in branches controller. !9710 (George Andrinopoulos)
|
||||||
- Refactor dropdown_assignee_spec. !9711 (George Andrinopoulos)
|
- Refactor dropdown_assignee_spec. !9711 (George Andrinopoulos)
|
||||||
- Delete artifacts for pages unless expiry date is specified. !9716
|
- Delete artifacts for pages unless expiry date is specified. !9716
|
||||||
|
|
|
@ -36,7 +36,7 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._
|
||||||
- [Release Scoping labels](#release-scoping-labels)
|
- [Release Scoping labels](#release-scoping-labels)
|
||||||
- [Priority labels](#priority-labels)
|
- [Priority labels](#priority-labels)
|
||||||
- [Severity labels](#severity-labels)
|
- [Severity labels](#severity-labels)
|
||||||
- [Severity impact guidance](#severity-impact-guidance)
|
- [Severity impact guidance](#severity-impact-guidance)
|
||||||
- [Label for community contributors](#label-for-community-contributors)
|
- [Label for community contributors](#label-for-community-contributors)
|
||||||
- [Implement design & UI elements](#implement-design--ui-elements)
|
- [Implement design & UI elements](#implement-design--ui-elements)
|
||||||
- [Issue tracker](#issue-tracker)
|
- [Issue tracker](#issue-tracker)
|
||||||
|
@ -70,13 +70,15 @@ to contribute to GitLab in a way that is easy for everyone.
|
||||||
For a first-time step-by-step guide to the contribution process, please see
|
For a first-time step-by-step guide to the contribution process, please see
|
||||||
["Contributing to GitLab"](https://about.gitlab.com/contributing/).
|
["Contributing to GitLab"](https://about.gitlab.com/contributing/).
|
||||||
|
|
||||||
Looking for something to work on? Look for issues with the label [Accepting Merge Requests](#i-want-to-contribute).
|
Looking for something to work on? Look for issues in the [Backlog (Accepting merge requests) milestone](#i-want-to-contribute).
|
||||||
|
|
||||||
GitLab comes into two flavors, GitLab Community Edition (CE) our free and open
|
GitLab comes in two flavors, GitLab Community Edition (CE) our free and open
|
||||||
source edition, and GitLab Enterprise Edition (EE) which is our commercial
|
source edition, and GitLab Enterprise Edition (EE) which is our commercial
|
||||||
edition. Throughout this guide you will see references to CE and EE for
|
edition. Throughout this guide you will see references to CE and EE for
|
||||||
abbreviation.
|
abbreviation.
|
||||||
|
|
||||||
|
To get an overview of GitLab community membership including those that would be reviewing or merging your contributions, please visit [the community roles page](doc/development/contributing/community_roles.md).
|
||||||
|
|
||||||
If you want to know how the GitLab [core team]
|
If you want to know how the GitLab [core team]
|
||||||
operates please see [the GitLab contributing process](PROCESS.md).
|
operates please see [the GitLab contributing process](PROCESS.md).
|
||||||
|
|
||||||
|
@ -151,8 +153,8 @@ the remaining issues on the GitHub issue tracker.
|
||||||
|
|
||||||
## I want to contribute!
|
## I want to contribute!
|
||||||
|
|
||||||
If you want to contribute to GitLab [issues with the label `Accepting Merge Requests` and small weight][accepting-mrs-weight]
|
If you want to contribute to GitLab, [issues in the Backlog (Accepting merge requests)](https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&utf8=✓&state=opened&assignee_id=0&milestone_title=Backlog%20(Accepting%20merge%20requests))
|
||||||
is a great place to start. Issues with a lower weight (1 or 2) are deemed
|
are a great place to start. Issues with a lower weight (1 or 2) are deemed
|
||||||
suitable for beginners. These issues will be of reasonable size and challenge,
|
suitable for beginners. These issues will be of reasonable size and challenge,
|
||||||
for anyone to start contributing to GitLab. If you have any questions or need help visit [Getting Help](https://about.gitlab.com/getting-help/#discussion) to
|
for anyone to start contributing to GitLab. If you have any questions or need help visit [Getting Help](https://about.gitlab.com/getting-help/#discussion) to
|
||||||
learn how to communicate with GitLab. If you're looking for a Gitter or Slack channel
|
learn how to communicate with GitLab. If you're looking for a Gitter or Slack channel
|
||||||
|
|
|
@ -6,3 +6,6 @@ danger.import_dangerfile(path: 'danger/gemfile')
|
||||||
danger.import_dangerfile(path: 'danger/database')
|
danger.import_dangerfile(path: 'danger/database')
|
||||||
danger.import_dangerfile(path: 'danger/documentation')
|
danger.import_dangerfile(path: 'danger/documentation')
|
||||||
danger.import_dangerfile(path: 'danger/frozen_string')
|
danger.import_dangerfile(path: 'danger/frozen_string')
|
||||||
|
danger.import_dangerfile(path: 'danger/commit_messages')
|
||||||
|
danger.import_dangerfile(path: 'danger/prettier')
|
||||||
|
danger.import_dangerfile(path: 'danger/eslint')
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.120.1
|
0.125.1
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
6.1.2
|
7.0.1
|
||||||
|
|
17
Gemfile
|
@ -80,16 +80,14 @@ gem 'gitlab_omniauth-ldap', '~> 2.0.4', require: 'omniauth-ldap'
|
||||||
gem 'net-ldap'
|
gem 'net-ldap'
|
||||||
|
|
||||||
# Git Wiki
|
# Git Wiki
|
||||||
# Required manually in config/initializers/gollum.rb to control load order
|
# Only used to compute wiki page slugs
|
||||||
gem 'gitlab-gollum-lib', '~> 4.2', require: false
|
gem 'gitlab-gollum-lib', '~> 4.2', require: false
|
||||||
|
|
||||||
gem 'gitlab-gollum-rugged_adapter', '~> 0.4.4', require: false
|
|
||||||
|
|
||||||
# Language detection
|
# Language detection
|
||||||
gem 'github-linguist', '~> 5.3.3', require: 'linguist'
|
gem 'github-linguist', '~> 5.3.3', require: 'linguist'
|
||||||
|
|
||||||
# API
|
# API
|
||||||
gem 'grape', '~> 1.0'
|
gem 'grape', '~> 1.1'
|
||||||
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'
|
||||||
|
|
||||||
|
@ -112,9 +110,6 @@ gem 'hamlit', '~> 2.8.8'
|
||||||
gem 'carrierwave', '= 1.2.3'
|
gem 'carrierwave', '= 1.2.3'
|
||||||
gem 'mini_magick'
|
gem 'mini_magick'
|
||||||
|
|
||||||
# Drag and Drop UI
|
|
||||||
gem 'dropzonejs-rails', '~> 0.7.1'
|
|
||||||
|
|
||||||
# for backups
|
# for backups
|
||||||
gem 'fog-aws', '~> 2.0.1'
|
gem 'fog-aws', '~> 2.0.1'
|
||||||
gem 'fog-core', '~> 1.44'
|
gem 'fog-core', '~> 1.44'
|
||||||
|
@ -137,6 +132,7 @@ gem 'seed-fu', '~> 2.3.7'
|
||||||
gem 'html-pipeline', '~> 2.8'
|
gem 'html-pipeline', '~> 2.8'
|
||||||
gem 'deckar01-task_list', '2.0.0'
|
gem 'deckar01-task_list', '2.0.0'
|
||||||
gem 'gitlab-markup', '~> 1.6.4'
|
gem 'gitlab-markup', '~> 1.6.4'
|
||||||
|
gem 'github-markup', '~> 1.7.0', require: 'github/markup'
|
||||||
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'
|
||||||
|
@ -170,10 +166,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.1'
|
gem 'sidekiq', '~> 5.2.1'
|
||||||
gem 'sidekiq-cron', '~> 0.6.0'
|
gem 'sidekiq-cron', '~> 0.6.0'
|
||||||
gem 'redis-namespace', '~> 1.6.0'
|
gem 'redis-namespace', '~> 1.6.0'
|
||||||
gem 'sidekiq-limit_fetch', '~> 3.4', require: false
|
|
||||||
|
|
||||||
# Cron Parser
|
# Cron Parser
|
||||||
gem 'rufus-scheduler', '~> 3.4'
|
gem 'rufus-scheduler', '~> 3.4'
|
||||||
|
@ -300,7 +295,7 @@ gem 'peek-mysql2', '~> 1.1.0', group: :mysql
|
||||||
gem 'peek-pg', '~> 1.3.0', group: :postgres
|
gem 'peek-pg', '~> 1.3.0', group: :postgres
|
||||||
gem 'peek-rblineprof', '~> 0.2.0'
|
gem 'peek-rblineprof', '~> 0.2.0'
|
||||||
gem 'peek-redis', '~> 1.2.0'
|
gem 'peek-redis', '~> 1.2.0'
|
||||||
gem 'peek-sidekiq', '~> 1.0.3'
|
gem 'gitlab-sidekiq-fetcher', require: 'sidekiq-reliable-fetch'
|
||||||
|
|
||||||
# Metrics
|
# Metrics
|
||||||
group :metrics do
|
group :metrics do
|
||||||
|
@ -425,7 +420,7 @@ group :ed25519 do
|
||||||
end
|
end
|
||||||
|
|
||||||
# Gitaly GRPC client
|
# Gitaly GRPC client
|
||||||
gem 'gitaly-proto', '~> 0.117.0', require: 'gitaly'
|
gem 'gitaly-proto', '~> 0.118.1', 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
|
||||||
|
|
62
Gemfile.lock
|
@ -86,7 +86,7 @@ GEM
|
||||||
bindata (2.4.3)
|
bindata (2.4.3)
|
||||||
binding_of_caller (0.7.2)
|
binding_of_caller (0.7.2)
|
||||||
debug_inspector (>= 0.0.1)
|
debug_inspector (>= 0.0.1)
|
||||||
bootsnap (1.3.1)
|
bootsnap (1.3.2)
|
||||||
msgpack (~> 1.0)
|
msgpack (~> 1.0)
|
||||||
bootstrap_form (2.7.0)
|
bootstrap_form (2.7.0)
|
||||||
brakeman (4.2.1)
|
brakeman (4.2.1)
|
||||||
|
@ -133,14 +133,14 @@ GEM
|
||||||
concurrent-ruby (1.0.5)
|
concurrent-ruby (1.0.5)
|
||||||
concurrent-ruby-ext (1.0.5)
|
concurrent-ruby-ext (1.0.5)
|
||||||
concurrent-ruby (= 1.0.5)
|
concurrent-ruby (= 1.0.5)
|
||||||
connection_pool (2.2.1)
|
connection_pool (2.2.2)
|
||||||
crack (0.4.3)
|
crack (0.4.3)
|
||||||
safe_yaml (~> 1.0.0)
|
safe_yaml (~> 1.0.0)
|
||||||
crass (1.0.4)
|
crass (1.0.4)
|
||||||
creole (0.5.0)
|
creole (0.5.0)
|
||||||
css_parser (1.5.0)
|
css_parser (1.5.0)
|
||||||
addressable
|
addressable
|
||||||
daemons (1.2.3)
|
daemons (1.2.6)
|
||||||
database_cleaner (1.5.3)
|
database_cleaner (1.5.3)
|
||||||
debug_inspector (0.0.2)
|
debug_inspector (0.0.2)
|
||||||
debugger-ruby_core_source (1.3.8)
|
debugger-ruby_core_source (1.3.8)
|
||||||
|
@ -175,8 +175,6 @@ GEM
|
||||||
doorkeeper-openid_connect (1.5.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)
|
|
||||||
rails (> 3.1)
|
|
||||||
ed25519 (1.2.4)
|
ed25519 (1.2.4)
|
||||||
email_reply_trimmer (0.1.6)
|
email_reply_trimmer (0.1.6)
|
||||||
email_spec (2.2.0)
|
email_spec (2.2.0)
|
||||||
|
@ -189,7 +187,7 @@ GEM
|
||||||
escape_utils (1.1.1)
|
escape_utils (1.1.1)
|
||||||
et-orbi (1.0.3)
|
et-orbi (1.0.3)
|
||||||
tzinfo
|
tzinfo
|
||||||
eventmachine (1.0.8)
|
eventmachine (1.2.7)
|
||||||
excon (0.62.0)
|
excon (0.62.0)
|
||||||
execjs (2.6.0)
|
execjs (2.6.0)
|
||||||
expression_parser (0.9.0)
|
expression_parser (0.9.0)
|
||||||
|
@ -276,7 +274,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)
|
||||||
gitaly-proto (0.117.0)
|
gitaly-proto (0.118.1)
|
||||||
google-protobuf (~> 3.1)
|
google-protobuf (~> 3.1)
|
||||||
grpc (~> 1.10)
|
grpc (~> 1.10)
|
||||||
github-linguist (5.3.3)
|
github-linguist (5.3.3)
|
||||||
|
@ -297,15 +295,14 @@ 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.1)
|
|
||||||
mime-types (>= 1.15)
|
|
||||||
rugged (~> 0.25)
|
|
||||||
gitlab-grit (2.8.2)
|
gitlab-grit (2.8.2)
|
||||||
charlock_holmes (~> 0.6)
|
charlock_holmes (~> 0.6)
|
||||||
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.4)
|
gitlab-markup (1.6.4)
|
||||||
|
gitlab-sidekiq-fetcher (0.3.0)
|
||||||
|
sidekiq (~> 5)
|
||||||
gitlab-styles (2.4.1)
|
gitlab-styles (2.4.1)
|
||||||
rubocop (~> 0.54.0)
|
rubocop (~> 0.54.0)
|
||||||
rubocop-gitlab-security (~> 0.1.0)
|
rubocop-gitlab-security (~> 0.1.0)
|
||||||
|
@ -343,7 +340,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.3)
|
grape (1.1.0)
|
||||||
activesupport
|
activesupport
|
||||||
builder
|
builder
|
||||||
mustermann-grape (~> 1.0.0)
|
mustermann-grape (~> 1.0.0)
|
||||||
|
@ -493,7 +490,7 @@ GEM
|
||||||
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_magick (4.8.0)
|
||||||
mini_mime (1.0.0)
|
mini_mime (1.0.1)
|
||||||
mini_portile2 (2.3.0)
|
mini_portile2 (2.3.0)
|
||||||
minitest (5.7.0)
|
minitest (5.7.0)
|
||||||
mousetrap-rails (1.4.6)
|
mousetrap-rails (1.4.6)
|
||||||
|
@ -501,7 +498,7 @@ GEM
|
||||||
multi_json (1.13.1)
|
multi_json (1.13.1)
|
||||||
multi_xml (0.6.0)
|
multi_xml (0.6.0)
|
||||||
multipart-post (2.0.0)
|
multipart-post (2.0.0)
|
||||||
mustermann (1.0.2)
|
mustermann (1.0.3)
|
||||||
mustermann-grape (1.0.0)
|
mustermann-grape (1.0.0)
|
||||||
mustermann (~> 1.0.0)
|
mustermann (~> 1.0.0)
|
||||||
mysql2 (0.4.10)
|
mysql2 (0.4.10)
|
||||||
|
@ -605,10 +602,6 @@ GEM
|
||||||
atomic (>= 1.0.0)
|
atomic (>= 1.0.0)
|
||||||
peek
|
peek
|
||||||
redis
|
redis
|
||||||
peek-sidekiq (1.0.3)
|
|
||||||
atomic (>= 1.0.0)
|
|
||||||
peek
|
|
||||||
sidekiq
|
|
||||||
pg (0.18.4)
|
pg (0.18.4)
|
||||||
po_to_json (1.0.1)
|
po_to_json (1.0.1)
|
||||||
json (>= 1.6.0)
|
json (>= 1.6.0)
|
||||||
|
@ -633,9 +626,9 @@ GEM
|
||||||
pry-byebug (3.4.3)
|
pry-byebug (3.4.3)
|
||||||
byebug (>= 9.0, < 9.1)
|
byebug (>= 9.0, < 9.1)
|
||||||
pry (~> 0.10)
|
pry (~> 0.10)
|
||||||
pry-rails (0.3.5)
|
pry-rails (0.3.6)
|
||||||
pry (>= 0.9.10)
|
pry (>= 0.10.4)
|
||||||
public_suffix (3.0.2)
|
public_suffix (3.0.3)
|
||||||
pyu-ruby-sasl (0.0.3.3)
|
pyu-ruby-sasl (0.0.3.3)
|
||||||
rack (1.6.10)
|
rack (1.6.10)
|
||||||
rack-accept (0.4.5)
|
rack-accept (0.4.5)
|
||||||
|
@ -649,7 +642,7 @@ GEM
|
||||||
httpclient (>= 2.4)
|
httpclient (>= 2.4)
|
||||||
multi_json (>= 1.3.6)
|
multi_json (>= 1.3.6)
|
||||||
rack (>= 1.1)
|
rack (>= 1.1)
|
||||||
rack-protection (2.0.1)
|
rack-protection (2.0.3)
|
||||||
rack
|
rack
|
||||||
rack-proxy (0.6.0)
|
rack-proxy (0.6.0)
|
||||||
rack
|
rack
|
||||||
|
@ -735,7 +728,7 @@ GEM
|
||||||
retriable (3.1.2)
|
retriable (3.1.2)
|
||||||
rinku (2.0.0)
|
rinku (2.0.0)
|
||||||
rotp (2.1.2)
|
rotp (2.1.2)
|
||||||
rouge (3.2.1)
|
rouge (3.3.0)
|
||||||
rqrcode (0.7.0)
|
rqrcode (0.7.0)
|
||||||
chunky_png
|
chunky_png
|
||||||
rqrcode-rails3 (0.1.7)
|
rqrcode-rails3 (0.1.7)
|
||||||
|
@ -843,16 +836,13 @@ GEM
|
||||||
rack
|
rack
|
||||||
shoulda-matchers (3.1.2)
|
shoulda-matchers (3.1.2)
|
||||||
activesupport (>= 4.0.0)
|
activesupport (>= 4.0.0)
|
||||||
sidekiq (5.1.3)
|
sidekiq (5.2.1)
|
||||||
concurrent-ruby (~> 1.0)
|
connection_pool (~> 2.2, >= 2.2.2)
|
||||||
connection_pool (~> 2.2, >= 2.2.0)
|
|
||||||
rack-protection (>= 1.5.0)
|
rack-protection (>= 1.5.0)
|
||||||
redis (>= 3.3.5, < 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)
|
||||||
sidekiq-limit_fetch (3.4.0)
|
|
||||||
sidekiq (>= 4)
|
|
||||||
signet (0.8.1)
|
signet (0.8.1)
|
||||||
addressable (~> 2.3)
|
addressable (~> 2.3)
|
||||||
faraday (~> 0.9)
|
faraday (~> 0.9)
|
||||||
|
@ -865,7 +855,7 @@ GEM
|
||||||
simplecov-html (~> 0.10.0)
|
simplecov-html (~> 0.10.0)
|
||||||
simplecov-html (0.10.0)
|
simplecov-html (0.10.0)
|
||||||
slack-notifier (1.5.1)
|
slack-notifier (1.5.1)
|
||||||
spring (2.0.1)
|
spring (2.0.2)
|
||||||
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)
|
||||||
|
@ -895,7 +885,7 @@ GEM
|
||||||
test_after_commit (1.1.0)
|
test_after_commit (1.1.0)
|
||||||
activerecord (>= 3.2)
|
activerecord (>= 3.2)
|
||||||
text (1.3.1)
|
text (1.3.1)
|
||||||
thin (1.7.0)
|
thin (1.7.2)
|
||||||
daemons (~> 1.0, >= 1.0.9)
|
daemons (~> 1.0, >= 1.0.9)
|
||||||
eventmachine (~> 1.0, >= 1.0.4)
|
eventmachine (~> 1.0, >= 1.0.4)
|
||||||
rack (>= 1, < 3)
|
rack (>= 1, < 3)
|
||||||
|
@ -954,7 +944,7 @@ GEM
|
||||||
addressable (>= 2.3.6)
|
addressable (>= 2.3.6)
|
||||||
crack (>= 0.3.2)
|
crack (>= 0.3.2)
|
||||||
hashdiff
|
hashdiff
|
||||||
webpack-rails (0.9.10)
|
webpack-rails (0.9.11)
|
||||||
railties (>= 3.2.0)
|
railties (>= 3.2.0)
|
||||||
wikicloth (0.8.1)
|
wikicloth (0.8.1)
|
||||||
builder
|
builder
|
||||||
|
@ -1013,7 +1003,6 @@ DEPENDENCIES
|
||||||
diffy (~> 3.1.0)
|
diffy (~> 3.1.0)
|
||||||
doorkeeper (~> 4.3)
|
doorkeeper (~> 4.3)
|
||||||
doorkeeper-openid_connect (~> 1.5)
|
doorkeeper-openid_connect (~> 1.5)
|
||||||
dropzonejs-rails (~> 0.7.1)
|
|
||||||
ed25519 (~> 1.2)
|
ed25519 (~> 1.2)
|
||||||
email_reply_trimmer (~> 0.1)
|
email_reply_trimmer (~> 0.1)
|
||||||
email_spec (~> 2.2.0)
|
email_spec (~> 2.2.0)
|
||||||
|
@ -1038,19 +1027,20 @@ 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.117.0)
|
gitaly-proto (~> 0.118.1)
|
||||||
github-linguist (~> 5.3.3)
|
github-linguist (~> 5.3.3)
|
||||||
|
github-markup (~> 1.7.0)
|
||||||
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-markup (~> 1.6.4)
|
gitlab-markup (~> 1.6.4)
|
||||||
|
gitlab-sidekiq-fetcher
|
||||||
gitlab-styles (~> 2.4)
|
gitlab-styles (~> 2.4)
|
||||||
gitlab_omniauth-ldap (~> 2.0.4)
|
gitlab_omniauth-ldap (~> 2.0.4)
|
||||||
gon (~> 6.2)
|
gon (~> 6.2)
|
||||||
google-api-client (~> 0.23)
|
google-api-client (~> 0.23)
|
||||||
google-protobuf (= 3.5.1)
|
google-protobuf (= 3.5.1)
|
||||||
gpgme
|
gpgme
|
||||||
grape (~> 1.0)
|
grape (~> 1.1)
|
||||||
grape-entity (~> 0.7.1)
|
grape-entity (~> 0.7.1)
|
||||||
grape-path-helpers (~> 1.0)
|
grape-path-helpers (~> 1.0)
|
||||||
grape_logging (~> 1.7)
|
grape_logging (~> 1.7)
|
||||||
|
@ -1114,7 +1104,6 @@ DEPENDENCIES
|
||||||
peek-pg (~> 1.3.0)
|
peek-pg (~> 1.3.0)
|
||||||
peek-rblineprof (~> 0.2.0)
|
peek-rblineprof (~> 0.2.0)
|
||||||
peek-redis (~> 1.2.0)
|
peek-redis (~> 1.2.0)
|
||||||
peek-sidekiq (~> 1.0.3)
|
|
||||||
pg (~> 0.18.2)
|
pg (~> 0.18.2)
|
||||||
premailer-rails (~> 1.9.7)
|
premailer-rails (~> 1.9.7)
|
||||||
prometheus-client-mmap (~> 0.9.4)
|
prometheus-client-mmap (~> 0.9.4)
|
||||||
|
@ -1166,9 +1155,8 @@ DEPENDENCIES
|
||||||
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.1)
|
sidekiq (~> 5.2.1)
|
||||||
sidekiq-cron (~> 0.6.0)
|
sidekiq-cron (~> 0.6.0)
|
||||||
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)
|
||||||
|
|
|
@ -89,7 +89,7 @@ GEM
|
||||||
bindata (2.4.3)
|
bindata (2.4.3)
|
||||||
binding_of_caller (0.7.2)
|
binding_of_caller (0.7.2)
|
||||||
debug_inspector (>= 0.0.1)
|
debug_inspector (>= 0.0.1)
|
||||||
bootsnap (1.3.1)
|
bootsnap (1.3.2)
|
||||||
msgpack (~> 1.0)
|
msgpack (~> 1.0)
|
||||||
bootstrap_form (2.7.0)
|
bootstrap_form (2.7.0)
|
||||||
brakeman (4.2.1)
|
brakeman (4.2.1)
|
||||||
|
@ -128,7 +128,7 @@ GEM
|
||||||
coderay (1.1.2)
|
coderay (1.1.2)
|
||||||
coercible (1.0.0)
|
coercible (1.0.0)
|
||||||
descendants_tracker (~> 0.0.1)
|
descendants_tracker (~> 0.0.1)
|
||||||
commonmarker (0.17.8)
|
commonmarker (0.17.13)
|
||||||
ruby-enum (~> 0.5)
|
ruby-enum (~> 0.5)
|
||||||
concord (0.1.5)
|
concord (0.1.5)
|
||||||
adamantium (~> 0.2.0)
|
adamantium (~> 0.2.0)
|
||||||
|
@ -136,14 +136,14 @@ GEM
|
||||||
concurrent-ruby (1.0.5)
|
concurrent-ruby (1.0.5)
|
||||||
concurrent-ruby-ext (1.0.5)
|
concurrent-ruby-ext (1.0.5)
|
||||||
concurrent-ruby (= 1.0.5)
|
concurrent-ruby (= 1.0.5)
|
||||||
connection_pool (2.2.1)
|
connection_pool (2.2.2)
|
||||||
crack (0.4.3)
|
crack (0.4.3)
|
||||||
safe_yaml (~> 1.0.0)
|
safe_yaml (~> 1.0.0)
|
||||||
crass (1.0.4)
|
crass (1.0.4)
|
||||||
creole (0.5.0)
|
creole (0.5.0)
|
||||||
css_parser (1.5.0)
|
css_parser (1.5.0)
|
||||||
addressable
|
addressable
|
||||||
daemons (1.2.3)
|
daemons (1.2.6)
|
||||||
database_cleaner (1.5.3)
|
database_cleaner (1.5.3)
|
||||||
debug_inspector (0.0.2)
|
debug_inspector (0.0.2)
|
||||||
debugger-ruby_core_source (1.3.8)
|
debugger-ruby_core_source (1.3.8)
|
||||||
|
@ -178,8 +178,6 @@ GEM
|
||||||
doorkeeper-openid_connect (1.5.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)
|
|
||||||
rails (> 3.1)
|
|
||||||
ed25519 (1.2.4)
|
ed25519 (1.2.4)
|
||||||
email_reply_trimmer (0.1.6)
|
email_reply_trimmer (0.1.6)
|
||||||
email_spec (2.2.0)
|
email_spec (2.2.0)
|
||||||
|
@ -192,7 +190,7 @@ GEM
|
||||||
escape_utils (1.1.1)
|
escape_utils (1.1.1)
|
||||||
et-orbi (1.0.3)
|
et-orbi (1.0.3)
|
||||||
tzinfo
|
tzinfo
|
||||||
eventmachine (1.0.8)
|
eventmachine (1.2.7)
|
||||||
excon (0.62.0)
|
excon (0.62.0)
|
||||||
execjs (2.6.0)
|
execjs (2.6.0)
|
||||||
expression_parser (0.9.0)
|
expression_parser (0.9.0)
|
||||||
|
@ -279,7 +277,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)
|
||||||
gitaly-proto (0.117.0)
|
gitaly-proto (0.118.1)
|
||||||
google-protobuf (~> 3.1)
|
google-protobuf (~> 3.1)
|
||||||
grpc (~> 1.10)
|
grpc (~> 1.10)
|
||||||
github-linguist (5.3.3)
|
github-linguist (5.3.3)
|
||||||
|
@ -300,15 +298,14 @@ 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.1)
|
|
||||||
mime-types (>= 1.15)
|
|
||||||
rugged (~> 0.25)
|
|
||||||
gitlab-grit (2.8.2)
|
gitlab-grit (2.8.2)
|
||||||
charlock_holmes (~> 0.6)
|
charlock_holmes (~> 0.6)
|
||||||
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.4)
|
gitlab-markup (1.6.4)
|
||||||
|
gitlab-sidekiq-fetcher (0.3.0)
|
||||||
|
sidekiq (~> 5)
|
||||||
gitlab-styles (2.4.1)
|
gitlab-styles (2.4.1)
|
||||||
rubocop (~> 0.54.0)
|
rubocop (~> 0.54.0)
|
||||||
rubocop-gitlab-security (~> 0.1.0)
|
rubocop-gitlab-security (~> 0.1.0)
|
||||||
|
@ -346,7 +343,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.3)
|
grape (1.1.0)
|
||||||
activesupport
|
activesupport
|
||||||
builder
|
builder
|
||||||
mustermann-grape (~> 1.0.0)
|
mustermann-grape (~> 1.0.0)
|
||||||
|
@ -412,7 +409,7 @@ GEM
|
||||||
json (~> 1.8)
|
json (~> 1.8)
|
||||||
multi_xml (>= 0.5.2)
|
multi_xml (>= 0.5.2)
|
||||||
httpclient (2.8.3)
|
httpclient (2.8.3)
|
||||||
i18n (1.0.1)
|
i18n (1.1.0)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
icalendar (2.4.1)
|
icalendar (2.4.1)
|
||||||
ice_nine (0.11.2)
|
ice_nine (0.11.2)
|
||||||
|
@ -496,7 +493,7 @@ GEM
|
||||||
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_magick (4.8.0)
|
||||||
mini_mime (1.0.0)
|
mini_mime (1.0.1)
|
||||||
mini_portile2 (2.3.0)
|
mini_portile2 (2.3.0)
|
||||||
minitest (5.7.0)
|
minitest (5.7.0)
|
||||||
mousetrap-rails (1.4.6)
|
mousetrap-rails (1.4.6)
|
||||||
|
@ -504,7 +501,7 @@ GEM
|
||||||
multi_json (1.13.1)
|
multi_json (1.13.1)
|
||||||
multi_xml (0.6.0)
|
multi_xml (0.6.0)
|
||||||
multipart-post (2.0.0)
|
multipart-post (2.0.0)
|
||||||
mustermann (1.0.2)
|
mustermann (1.0.3)
|
||||||
mustermann-grape (1.0.0)
|
mustermann-grape (1.0.0)
|
||||||
mustermann (~> 1.0.0)
|
mustermann (~> 1.0.0)
|
||||||
mysql2 (0.4.10)
|
mysql2 (0.4.10)
|
||||||
|
@ -609,10 +606,6 @@ GEM
|
||||||
atomic (>= 1.0.0)
|
atomic (>= 1.0.0)
|
||||||
peek
|
peek
|
||||||
redis
|
redis
|
||||||
peek-sidekiq (1.0.3)
|
|
||||||
atomic (>= 1.0.0)
|
|
||||||
peek
|
|
||||||
sidekiq
|
|
||||||
pg (0.18.4)
|
pg (0.18.4)
|
||||||
po_to_json (1.0.1)
|
po_to_json (1.0.1)
|
||||||
json (>= 1.6.0)
|
json (>= 1.6.0)
|
||||||
|
@ -637,9 +630,9 @@ GEM
|
||||||
pry-byebug (3.4.3)
|
pry-byebug (3.4.3)
|
||||||
byebug (>= 9.0, < 9.1)
|
byebug (>= 9.0, < 9.1)
|
||||||
pry (~> 0.10)
|
pry (~> 0.10)
|
||||||
pry-rails (0.3.5)
|
pry-rails (0.3.6)
|
||||||
pry (>= 0.9.10)
|
pry (>= 0.10.4)
|
||||||
public_suffix (3.0.2)
|
public_suffix (3.0.3)
|
||||||
pyu-ruby-sasl (0.0.3.3)
|
pyu-ruby-sasl (0.0.3.3)
|
||||||
rack (2.0.5)
|
rack (2.0.5)
|
||||||
rack-accept (0.4.5)
|
rack-accept (0.4.5)
|
||||||
|
@ -653,7 +646,7 @@ GEM
|
||||||
httpclient (>= 2.4)
|
httpclient (>= 2.4)
|
||||||
multi_json (>= 1.3.6)
|
multi_json (>= 1.3.6)
|
||||||
rack (>= 1.1)
|
rack (>= 1.1)
|
||||||
rack-protection (2.0.1)
|
rack-protection (2.0.3)
|
||||||
rack
|
rack
|
||||||
rack-proxy (0.6.0)
|
rack-proxy (0.6.0)
|
||||||
rack
|
rack
|
||||||
|
@ -744,7 +737,7 @@ GEM
|
||||||
retriable (3.1.2)
|
retriable (3.1.2)
|
||||||
rinku (2.0.0)
|
rinku (2.0.0)
|
||||||
rotp (2.1.2)
|
rotp (2.1.2)
|
||||||
rouge (3.2.1)
|
rouge (3.3.0)
|
||||||
rqrcode (0.7.0)
|
rqrcode (0.7.0)
|
||||||
chunky_png
|
chunky_png
|
||||||
rqrcode-rails3 (0.1.7)
|
rqrcode-rails3 (0.1.7)
|
||||||
|
@ -851,16 +844,13 @@ GEM
|
||||||
rack
|
rack
|
||||||
shoulda-matchers (3.1.2)
|
shoulda-matchers (3.1.2)
|
||||||
activesupport (>= 4.0.0)
|
activesupport (>= 4.0.0)
|
||||||
sidekiq (5.1.3)
|
sidekiq (5.2.1)
|
||||||
concurrent-ruby (~> 1.0)
|
connection_pool (~> 2.2, >= 2.2.2)
|
||||||
connection_pool (~> 2.2, >= 2.2.0)
|
|
||||||
rack-protection (>= 1.5.0)
|
rack-protection (>= 1.5.0)
|
||||||
redis (>= 3.3.5, < 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)
|
||||||
sidekiq-limit_fetch (3.4.0)
|
|
||||||
sidekiq (>= 4)
|
|
||||||
signet (0.8.1)
|
signet (0.8.1)
|
||||||
addressable (~> 2.3)
|
addressable (~> 2.3)
|
||||||
faraday (~> 0.9)
|
faraday (~> 0.9)
|
||||||
|
@ -873,7 +863,7 @@ GEM
|
||||||
simplecov-html (~> 0.10.0)
|
simplecov-html (~> 0.10.0)
|
||||||
simplecov-html (0.10.0)
|
simplecov-html (0.10.0)
|
||||||
slack-notifier (1.5.1)
|
slack-notifier (1.5.1)
|
||||||
spring (2.0.1)
|
spring (2.0.2)
|
||||||
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)
|
||||||
|
@ -901,7 +891,7 @@ GEM
|
||||||
temple (0.8.0)
|
temple (0.8.0)
|
||||||
test-prof (0.2.5)
|
test-prof (0.2.5)
|
||||||
text (1.3.1)
|
text (1.3.1)
|
||||||
thin (1.7.0)
|
thin (1.7.2)
|
||||||
daemons (~> 1.0, >= 1.0.9)
|
daemons (~> 1.0, >= 1.0.9)
|
||||||
eventmachine (~> 1.0, >= 1.0.4)
|
eventmachine (~> 1.0, >= 1.0.4)
|
||||||
rack (>= 1, < 3)
|
rack (>= 1, < 3)
|
||||||
|
@ -960,7 +950,7 @@ GEM
|
||||||
addressable (>= 2.3.6)
|
addressable (>= 2.3.6)
|
||||||
crack (>= 0.3.2)
|
crack (>= 0.3.2)
|
||||||
hashdiff
|
hashdiff
|
||||||
webpack-rails (0.9.10)
|
webpack-rails (0.9.11)
|
||||||
railties (>= 3.2.0)
|
railties (>= 3.2.0)
|
||||||
websocket-driver (0.6.5)
|
websocket-driver (0.6.5)
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
|
@ -1022,7 +1012,6 @@ DEPENDENCIES
|
||||||
diffy (~> 3.1.0)
|
diffy (~> 3.1.0)
|
||||||
doorkeeper (~> 4.3)
|
doorkeeper (~> 4.3)
|
||||||
doorkeeper-openid_connect (~> 1.5)
|
doorkeeper-openid_connect (~> 1.5)
|
||||||
dropzonejs-rails (~> 0.7.1)
|
|
||||||
ed25519 (~> 1.2)
|
ed25519 (~> 1.2)
|
||||||
email_reply_trimmer (~> 0.1)
|
email_reply_trimmer (~> 0.1)
|
||||||
email_spec (~> 2.2.0)
|
email_spec (~> 2.2.0)
|
||||||
|
@ -1047,19 +1036,20 @@ 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.117.0)
|
gitaly-proto (~> 0.118.1)
|
||||||
github-linguist (~> 5.3.3)
|
github-linguist (~> 5.3.3)
|
||||||
|
github-markup (~> 1.7.0)
|
||||||
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-markup (~> 1.6.4)
|
gitlab-markup (~> 1.6.4)
|
||||||
|
gitlab-sidekiq-fetcher
|
||||||
gitlab-styles (~> 2.4)
|
gitlab-styles (~> 2.4)
|
||||||
gitlab_omniauth-ldap (~> 2.0.4)
|
gitlab_omniauth-ldap (~> 2.0.4)
|
||||||
gon (~> 6.2)
|
gon (~> 6.2)
|
||||||
google-api-client (~> 0.23)
|
google-api-client (~> 0.23)
|
||||||
google-protobuf (= 3.5.1)
|
google-protobuf (= 3.5.1)
|
||||||
gpgme
|
gpgme
|
||||||
grape (~> 1.0)
|
grape (~> 1.1)
|
||||||
grape-entity (~> 0.7.1)
|
grape-entity (~> 0.7.1)
|
||||||
grape-path-helpers (~> 1.0)
|
grape-path-helpers (~> 1.0)
|
||||||
grape_logging (~> 1.7)
|
grape_logging (~> 1.7)
|
||||||
|
@ -1123,7 +1113,6 @@ DEPENDENCIES
|
||||||
peek-pg (~> 1.3.0)
|
peek-pg (~> 1.3.0)
|
||||||
peek-rblineprof (~> 0.2.0)
|
peek-rblineprof (~> 0.2.0)
|
||||||
peek-redis (~> 1.2.0)
|
peek-redis (~> 1.2.0)
|
||||||
peek-sidekiq (~> 1.0.3)
|
|
||||||
pg (~> 0.18.2)
|
pg (~> 0.18.2)
|
||||||
premailer-rails (~> 1.9.7)
|
premailer-rails (~> 1.9.7)
|
||||||
prometheus-client-mmap (~> 0.9.4)
|
prometheus-client-mmap (~> 0.9.4)
|
||||||
|
@ -1176,9 +1165,8 @@ DEPENDENCIES
|
||||||
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.1)
|
sidekiq (~> 5.2.1)
|
||||||
sidekiq-cron (~> 0.6.0)
|
sidekiq-cron (~> 0.6.0)
|
||||||
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)
|
||||||
|
|
18
LICENSE
|
@ -1,7 +1,19 @@
|
||||||
Copyright GitLab B.V.
|
Copyright GitLab B.V.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
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.
|
||||||
|
|
55
PROCESS.md
|
@ -74,14 +74,31 @@ star, smile, etc.). Some good tips about code reviews can be found in our
|
||||||
|
|
||||||
## Feature freeze on the 7th for the release on the 22nd
|
## Feature freeze on the 7th for the release on the 22nd
|
||||||
|
|
||||||
After 7th at 23:59 (Pacific Time Zone) of each month, RC1 of the upcoming release (to be shipped on the 22nd) is created and deployed to GitLab.com and the stable branch for this release is frozen, which means master is no longer merged into it.
|
After 7th at 23:59 (Pacific Time Zone) of each month, RC1 of the upcoming
|
||||||
Merge requests may still be merged into master during this period,
|
release (to be shipped on the 22nd) is created and deployed to GitLab.com and
|
||||||
but they will go into the _next_ release, unless they are manually cherry-picked into the stable branch.
|
the stable branch for this release is frozen, which means master is no longer
|
||||||
|
merged into it. Merge requests may still be merged into master during this
|
||||||
|
period, but they will go into the _next_ release, unless they are manually
|
||||||
|
cherry-picked into the stable branch.
|
||||||
|
|
||||||
By freezing the stable branches 2 weeks prior to a release, we reduce the risk of a last minute merge request potentially breaking things.
|
By freezing the stable branches 2 weeks prior to a release, we reduce the risk
|
||||||
|
of a last minute merge request potentially breaking things.
|
||||||
|
|
||||||
Any release candidate that gets created after this date can become a final release,
|
Any release candidate that gets created after this date can become a final
|
||||||
hence the name release candidate.
|
release, hence the name release candidate.
|
||||||
|
|
||||||
|
### Feature flags
|
||||||
|
|
||||||
|
Merge requests that make changes hidden behind a feature flag, or remove an
|
||||||
|
existing feature flag because a feature is deemed stable, may be merged (and
|
||||||
|
picked into the stable branches) up to the 19th of the month. Such merge
|
||||||
|
requests should have the ~"feature flag" label assigned, and don't require a
|
||||||
|
corresponding exception request to be created.
|
||||||
|
|
||||||
|
While rare, release managers may decide to reject picking a change into a stable
|
||||||
|
branch, even when feature flags are used. This might be necessary if the changes
|
||||||
|
are deemed problematic, too invasive, or there simply isn't enough time to
|
||||||
|
properly test how the changes behave on GitLab.com.
|
||||||
|
|
||||||
### Between the 1st and the 7th
|
### Between the 1st and the 7th
|
||||||
|
|
||||||
|
@ -223,36 +240,36 @@ Check [this guide](https://gitlab.com/gitlab-org/release/docs/blob/master/genera
|
||||||
|
|
||||||
A ~bug is a defect, error, failure which causes the system to behave incorrectly or prevents it from fulfilling the product requirements.
|
A ~bug is a defect, error, failure which causes the system to behave incorrectly or prevents it from fulfilling the product requirements.
|
||||||
|
|
||||||
The level of impact of a ~bug can vary from blocking a whole functionality
|
The level of impact of a ~bug can vary from blocking a whole functionality
|
||||||
or a feature usability bug. A bug should always be linked to a severity level.
|
or a feature usability bug. A bug should always be linked to a severity level.
|
||||||
Refer to our [severity levels](../CONTRIBUTING.md#severity-labels)
|
Refer to our [severity levels](../CONTRIBUTING.md#severity-labels)
|
||||||
|
|
||||||
Whether the bug is also a regression or not, the triage process should start as soon as possible.
|
Whether the bug is also a regression or not, the triage process should start as soon as possible.
|
||||||
Ensure that the Engineering Manager and/or the Product Manager for the relative area is involved to prioritize the work as needed.
|
Ensure that the Engineering Manager and/or the Product Manager for the relative area is involved to prioritize the work as needed.
|
||||||
|
|
||||||
### Regressions
|
### Regressions
|
||||||
|
|
||||||
A ~regression implies that a previously **verified working functionality** no longer works.
|
A ~regression implies that a previously **verified working functionality** no longer works.
|
||||||
Regressions are a subset of bugs. We use the ~regression label to imply that the defect caused the functionality to regress.
|
Regressions are a subset of bugs. We use the ~regression label to imply that the defect caused the functionality to regress.
|
||||||
The label tells us that something worked before and it needs extra attention from Engineering and Product Managers to schedule/reschedule.
|
The label tells us that something worked before and it needs extra attention from Engineering and Product Managers to schedule/reschedule.
|
||||||
|
|
||||||
The regression label does not apply to ~bugs for new features for which functionality was **never verified as working**.
|
The regression label does not apply to ~bugs for new features for which functionality was **never verified as working**.
|
||||||
These, by definition, are not regressions.
|
These, by definition, are not regressions.
|
||||||
|
|
||||||
A regression should always have the `regression:xx.x` label on it to designate when it was introduced.
|
A regression should always have the `regression:xx.x` label on it to designate when it was introduced.
|
||||||
|
|
||||||
Regressions should be considered high priority issues that should be solved as soon as possible, especially if they have severe impact on users.
|
Regressions should be considered high priority issues that should be solved as soon as possible, especially if they have severe impact on users.
|
||||||
|
|
||||||
### Managing bugs
|
### Managing bugs
|
||||||
|
|
||||||
**Prioritization:** We give higher priority to regressions on features that worked in the last recent monthly release and the current release candidates.
|
**Prioritization:** We give higher priority to regressions on features that worked in the last recent monthly release and the current release candidates.
|
||||||
The two scenarios below can [bypass the exception request in the release process](https://gitlab.com/gitlab-org/release/docs/blob/master/general/exception-request/process.md#after-the-7th), where the affected regression version matches the current monthly release version.
|
The two scenarios below can [bypass the exception request in the release process](https://gitlab.com/gitlab-org/release/docs/blob/master/general/exception-request/process.md#after-the-7th), where the affected regression version matches the current monthly release version.
|
||||||
* A regression which worked in the **Last monthly release**
|
* A regression which worked in the **Last monthly release**
|
||||||
* **Example:** In 11.0 we released a new `feature X` that is verified as working. Then in release 11.1 the feature no longer works, this is regression for 11.1. The issue should have the `regression:11.1` label.
|
* **Example:** In 11.0 we released a new `feature X` that is verified as working. Then in release 11.1 the feature no longer works, this is regression for 11.1. The issue should have the `regression:11.1` label.
|
||||||
* *Note:* When we say `the last recent monthly release`, this can refer to either the version currently running on GitLab.com, or the most recent version available in the package repositories.
|
* *Note:* When we say `the last recent monthly release`, this can refer to either the version currently running on GitLab.com, or the most recent version available in the package repositories.
|
||||||
* A regression which worked in the **Current release candidates**
|
* A regression which worked in the **Current release candidates**
|
||||||
* **Example:** In 11.1-RC3 we shipped a new feature which has been verified as working. Then in 11.1-RC5 the feature no longer works, this is regression for 11.1. The issue should have the `regression:11.1` label.
|
* **Example:** In 11.1-RC3 we shipped a new feature which has been verified as working. Then in 11.1-RC5 the feature no longer works, this is regression for 11.1. The issue should have the `regression:11.1` label.
|
||||||
* *Note:* Because GitLab.com runs release candidates of new releases, a regression can be reported in a release before its 'official' release date on the 22nd of the month.
|
* *Note:* Because GitLab.com runs release candidates of new releases, a regression can be reported in a release before its 'official' release date on the 22nd of the month.
|
||||||
|
|
||||||
When a bug is found:
|
When a bug is found:
|
||||||
1. Create an issue describing the problem in the most detailed way possible.
|
1. Create an issue describing the problem in the most detailed way possible.
|
||||||
|
@ -264,11 +281,11 @@ When a bug is found:
|
||||||
The counterpart Product Manager is included to weigh-in on prioritization as needed.
|
The counterpart Product Manager is included to weigh-in on prioritization as needed.
|
||||||
1. If the ~bug is **NOT** a regression:
|
1. If the ~bug is **NOT** a regression:
|
||||||
1. The Engineering Manager decides which milestone the bug will be fixed. The appropriate milestone is applied.
|
1. The Engineering Manager decides which milestone the bug will be fixed. The appropriate milestone is applied.
|
||||||
1. If the bug is a ~regression:
|
1. If the bug is a ~regression:
|
||||||
1. Determine the release that the regression affects and add the corresponding `regression:xx.x` label.
|
1. Determine the release that the regression affects and add the corresponding `regression:xx.x` label.
|
||||||
1. If the affected release version can't be determined, add the generic ~regression label for the time being.
|
1. If the affected release version can't be determined, add the generic ~regression label for the time being.
|
||||||
1. If the affected version `xx.x` in `regression:xx.x` is the **current release**, it's recommended to schedule the fix for the current milestone.
|
1. If the affected version `xx.x` in `regression:xx.x` is the **current release**, it's recommended to schedule the fix for the current milestone.
|
||||||
1. This falls under regressions which worked in the last release and the current RCs. More detailed explanations in the **Prioritization** section above.
|
1. This falls under regressions which worked in the last release and the current RCs. More detailed explanations in the **Prioritization** section above.
|
||||||
1. If the affected version `xx.x` in `regression:xx.x` is older than the **current release**
|
1. If the affected version `xx.x` in `regression:xx.x` is older than the **current release**
|
||||||
1. If the regression is an ~S1 severity, it's recommended to schedule the fix for the current milestone. We would like to fix the highest severity regression as soon as we can.
|
1. If the regression is an ~S1 severity, it's recommended to schedule the fix for the current milestone. We would like to fix the highest severity regression as soon as we can.
|
||||||
1. If the regression is an ~S2, ~S3 or ~S4 severity, the regression may be scheduled for later milestones at the discretion of the Engineering Manager and Product Manager.
|
1. If the regression is an ~S2, ~S3 or ~S4 severity, the regression may be scheduled for later milestones at the discretion of the Engineering Manager and Product Manager.
|
||||||
|
|
2
VERSION
|
@ -1 +1 @@
|
||||||
11.3.11
|
11.4.9
|
||||||
|
|
After Width: | Height: | Size: 5.3 KiB |
BIN
app/assets/images/ci_favicons/favicon_status_scheduled.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
app/assets/images/cluster_app_logos/elasticsearch.png
Normal file
After Width: | Height: | Size: 796 B |
BIN
app/assets/images/cluster_app_logos/gitlab.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
app/assets/images/cluster_app_logos/helm.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
app/assets/images/cluster_app_logos/jeager.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
app/assets/images/cluster_app_logos/jupyterhub.png
Normal file
After Width: | Height: | Size: 895 B |
BIN
app/assets/images/cluster_app_logos/kubernetes.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
app/assets/images/cluster_app_logos/meltano.png
Normal file
After Width: | Height: | Size: 580 B |
BIN
app/assets/images/cluster_app_logos/prometheus.png
Normal file
After Width: | Height: | Size: 923 B |
|
@ -15,13 +15,11 @@ const Api = {
|
||||||
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',
|
||||||
templatesPath: '/api/:version/templates/:key',
|
|
||||||
licensePath: '/api/:version/templates/licenses/:key',
|
|
||||||
gitignorePath: '/api/:version/templates/gitignores/:key',
|
|
||||||
gitlabCiYmlPath: '/api/:version/templates/gitlab_ci_ymls/:key',
|
|
||||||
dockerfilePath: '/api/:version/templates/dockerfiles/:key',
|
|
||||||
issuableTemplatePath: '/:namespace_path/:project_path/templates/:type/:key',
|
issuableTemplatePath: '/:namespace_path/:project_path/templates/:type/:key',
|
||||||
|
projectTemplatePath: '/api/:version/projects/:id/templates/:type/:key',
|
||||||
|
projectTemplatesPath: '/api/:version/projects/:id/templates/:type',
|
||||||
usersPath: '/api/:version/users.json',
|
usersPath: '/api/:version/users.json',
|
||||||
|
userStatusPath: '/api/:version/user/status',
|
||||||
commitPath: '/api/:version/projects/:id/repository/commits',
|
commitPath: '/api/:version/projects/:id/repository/commits',
|
||||||
commitPipelinesPath: '/:project_id/commit/:sha/pipelines',
|
commitPipelinesPath: '/:project_id/commit/:sha/pipelines',
|
||||||
branchSinglePath: '/api/:version/projects/:id/repository/branches/:branch',
|
branchSinglePath: '/api/:version/projects/:id/repository/branches/:branch',
|
||||||
|
@ -195,29 +193,29 @@ const Api = {
|
||||||
return axios.get(url);
|
return axios.get(url);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Return text for a specific license
|
projectTemplate(id, type, key, options, callback) {
|
||||||
licenseText(key, data, callback) {
|
const url = Api.buildUrl(this.projectTemplatePath)
|
||||||
const url = Api.buildUrl(Api.licensePath).replace(':key', key);
|
.replace(':id', encodeURIComponent(id))
|
||||||
return axios
|
.replace(':type', type)
|
||||||
.get(url, {
|
.replace(':key', encodeURIComponent(key));
|
||||||
params: data,
|
|
||||||
})
|
return axios.get(url, { params: options }).then(res => {
|
||||||
.then(res => callback(res.data));
|
if (callback) callback(res.data);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
gitignoreText(key, callback) {
|
projectTemplates(id, type, params = {}, callback) {
|
||||||
const url = Api.buildUrl(Api.gitignorePath).replace(':key', key);
|
const url = Api.buildUrl(this.projectTemplatesPath)
|
||||||
return axios.get(url).then(({ data }) => callback(data));
|
.replace(':id', encodeURIComponent(id))
|
||||||
},
|
.replace(':type', type);
|
||||||
|
|
||||||
gitlabCiYml(key, callback) {
|
return axios.get(url, { params }).then(res => {
|
||||||
const url = Api.buildUrl(Api.gitlabCiYmlPath).replace(':key', key);
|
if (callback) callback(res.data);
|
||||||
return axios.get(url).then(({ data }) => callback(data));
|
|
||||||
},
|
|
||||||
|
|
||||||
dockerfileYml(key, callback) {
|
return res;
|
||||||
const url = Api.buildUrl(Api.dockerfilePath).replace(':key', key);
|
});
|
||||||
return axios.get(url).then(({ data }) => callback(data));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
issueTemplate(namespacePath, projectPath, key, type, callback) {
|
issueTemplate(namespacePath, projectPath, key, type, callback) {
|
||||||
|
@ -266,10 +264,13 @@ const Api = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
templates(key, params = {}) {
|
postUserStatus({ emoji, message }) {
|
||||||
const url = Api.buildUrl(this.templatesPath).replace(':key', key);
|
const url = Api.buildUrl(this.userStatusPath);
|
||||||
|
|
||||||
return axios.get(url, { params });
|
return axios.put(url, {
|
||||||
|
emoji,
|
||||||
|
message,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
buildUrl(url) {
|
buildUrl(url) {
|
||||||
|
|
|
@ -42,10 +42,11 @@ export class AwardsHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
bindEvents() {
|
bindEvents() {
|
||||||
|
const $parentEl = this.targetContainerEl ? $(this.targetContainerEl) : $(document);
|
||||||
// If the user shows intent let's pre-build the menu
|
// If the user shows intent let's pre-build the menu
|
||||||
this.registerEventListener(
|
this.registerEventListener(
|
||||||
'one',
|
'one',
|
||||||
$(document),
|
$parentEl,
|
||||||
'mouseenter focus',
|
'mouseenter focus',
|
||||||
this.toggleButtonSelector,
|
this.toggleButtonSelector,
|
||||||
'mouseenter focus',
|
'mouseenter focus',
|
||||||
|
@ -58,7 +59,7 @@ export class AwardsHandler {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
this.registerEventListener('on', $(document), 'click', this.toggleButtonSelector, e => {
|
this.registerEventListener('on', $parentEl, 'click', this.toggleButtonSelector, e => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.showEmojiMenu($(e.currentTarget));
|
this.showEmojiMenu($(e.currentTarget));
|
||||||
|
@ -76,7 +77,7 @@ export class AwardsHandler {
|
||||||
});
|
});
|
||||||
|
|
||||||
const emojiButtonSelector = `.js-awards-block .js-emoji-btn, .${this.menuClass} .js-emoji-btn`;
|
const emojiButtonSelector = `.js-awards-block .js-emoji-btn, .${this.menuClass} .js-emoji-btn`;
|
||||||
this.registerEventListener('on', $(document), 'click', emojiButtonSelector, e => {
|
this.registerEventListener('on', $parentEl, 'click', emojiButtonSelector, 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');
|
||||||
|
@ -168,7 +169,8 @@ export class AwardsHandler {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
document.body.insertAdjacentHTML('beforeend', emojiMenuMarkup);
|
const targetEl = this.targetContainerEl ? this.targetContainerEl : document.body;
|
||||||
|
targetEl.insertAdjacentHTML('beforeend', emojiMenuMarkup);
|
||||||
|
|
||||||
this.addRemainingEmojiMenuCategories();
|
this.addRemainingEmojiMenuCategories();
|
||||||
this.setupSearch();
|
this.setupSearch();
|
||||||
|
@ -250,6 +252,12 @@ export class AwardsHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
positionMenu($menu, $addBtn) {
|
positionMenu($menu, $addBtn) {
|
||||||
|
if (this.targetContainerEl) {
|
||||||
|
return $menu.css({
|
||||||
|
top: `${$addBtn.outerHeight()}px`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const position = $addBtn.data('position');
|
const position = $addBtn.data('position');
|
||||||
// The menu could potentially be off-screen or in a hidden overflow element
|
// The menu could potentially be off-screen or in a hidden overflow element
|
||||||
// So we position the element absolute in the body
|
// So we position the element absolute in the body
|
||||||
|
@ -424,9 +432,7 @@ export class AwardsHandler {
|
||||||
users = origTitle.trim().split(FROM_SENTENCE_REGEX);
|
users = origTitle.trim().split(FROM_SENTENCE_REGEX);
|
||||||
}
|
}
|
||||||
users.unshift('You');
|
users.unshift('You');
|
||||||
return awardBlock
|
return awardBlock.attr('title', this.toSentence(users)).tooltip('_fixTitle');
|
||||||
.attr('title', this.toSentence(users))
|
|
||||||
.tooltip('_fixTitle');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createAwardButtonForVotesBlock(votesBlock, emojiName) {
|
createAwardButtonForVotesBlock(votesBlock, emojiName) {
|
||||||
|
@ -609,13 +615,11 @@ export 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').then(
|
awardsHandlerPromise = import(/* webpackChunkName: 'emoji' */ './emoji').then(Emoji => {
|
||||||
Emoji => {
|
const awardsHandler = new AwardsHandler(Emoji);
|
||||||
const awardsHandler = new AwardsHandler(Emoji);
|
awardsHandler.bindEvents();
|
||||||
awardsHandler.bindEvents();
|
return awardsHandler;
|
||||||
return awardsHandler;
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return awardsHandlerPromise;
|
return awardsHandlerPromise;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
import Icon from '~/vue_shared/components/icon.vue';
|
import Icon from '~/vue_shared/components/icon.vue';
|
||||||
import LoadingIcon from '~/vue_shared/components/loading_icon.vue';
|
|
||||||
import Tooltip from '~/vue_shared/directives/tooltip';
|
import Tooltip from '~/vue_shared/directives/tooltip';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Badge',
|
name: 'Badge',
|
||||||
components: {
|
components: {
|
||||||
Icon,
|
Icon,
|
||||||
LoadingIcon,
|
|
||||||
Tooltip,
|
Tooltip,
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
|
@ -80,7 +78,7 @@ export default {
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<loading-icon
|
<gl-loading-icon
|
||||||
v-show="isLoading"
|
v-show="isLoading"
|
||||||
:inline="true"
|
:inline="true"
|
||||||
/>
|
/>
|
||||||
|
@ -105,8 +103,8 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
v-tooltip
|
|
||||||
v-show="hasError"
|
v-show="hasError"
|
||||||
|
v-tooltip
|
||||||
:title="s__('Badges|Reload badge image')"
|
:title="s__('Badges|Reload badge image')"
|
||||||
class="btn btn-transparent btn-sm text-primary"
|
class="btn btn-transparent btn-sm text-primary"
|
||||||
type="button"
|
type="button"
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { mapActions, mapState } from 'vuex';
|
||||||
import createFlash from '~/flash';
|
import createFlash from '~/flash';
|
||||||
import { s__, sprintf } from '~/locale';
|
import { s__, sprintf } from '~/locale';
|
||||||
import LoadingButton from '~/vue_shared/components/loading_button.vue';
|
import LoadingButton from '~/vue_shared/components/loading_button.vue';
|
||||||
import LoadingIcon from '~/vue_shared/components/loading_icon.vue';
|
|
||||||
import createEmptyBadge from '../empty_badge';
|
import createEmptyBadge from '../empty_badge';
|
||||||
import Badge from './badge.vue';
|
import Badge from './badge.vue';
|
||||||
|
|
||||||
|
@ -15,7 +14,6 @@ export default {
|
||||||
components: {
|
components: {
|
||||||
Badge,
|
Badge,
|
||||||
LoadingButton,
|
LoadingButton,
|
||||||
LoadingIcon,
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
isEditing: {
|
isEditing: {
|
||||||
|
@ -207,7 +205,7 @@ export default {
|
||||||
:link-url="renderedLinkUrl"
|
:link-url="renderedLinkUrl"
|
||||||
/>
|
/>
|
||||||
<p v-show="isRendering">
|
<p v-show="isRendering">
|
||||||
<loading-icon
|
<gl-loading-icon
|
||||||
:inline="true"
|
:inline="true"
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from 'vuex';
|
import { mapState } from 'vuex';
|
||||||
import LoadingIcon from '~/vue_shared/components/loading_icon.vue';
|
|
||||||
import BadgeListRow from './badge_list_row.vue';
|
import BadgeListRow from './badge_list_row.vue';
|
||||||
import { GROUP_BADGE } from '../constants';
|
import { GROUP_BADGE } from '../constants';
|
||||||
|
|
||||||
|
@ -8,7 +7,6 @@ export default {
|
||||||
name: 'BadgeList',
|
name: 'BadgeList',
|
||||||
components: {
|
components: {
|
||||||
BadgeListRow,
|
BadgeListRow,
|
||||||
LoadingIcon,
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['badges', 'isLoading', 'kind']),
|
...mapState(['badges', 'isLoading', 'kind']),
|
||||||
|
@ -31,10 +29,10 @@ export default {
|
||||||
class="badge badge-pill"
|
class="badge badge-pill"
|
||||||
>{{ badges.length }}</span>
|
>{{ badges.length }}</span>
|
||||||
</div>
|
</div>
|
||||||
<loading-icon
|
<gl-loading-icon
|
||||||
v-show="isLoading"
|
v-show="isLoading"
|
||||||
|
:size="2"
|
||||||
class="card-body"
|
class="card-body"
|
||||||
size="2"
|
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="hasNoBadges"
|
v-if="hasNoBadges"
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
import { mapActions, mapState } from 'vuex';
|
import { mapActions, mapState } from 'vuex';
|
||||||
import { s__ } from '~/locale';
|
import { s__ } from '~/locale';
|
||||||
import Icon from '~/vue_shared/components/icon.vue';
|
import Icon from '~/vue_shared/components/icon.vue';
|
||||||
import LoadingIcon from '~/vue_shared/components/loading_icon.vue';
|
|
||||||
import { PROJECT_BADGE } from '../constants';
|
import { PROJECT_BADGE } from '../constants';
|
||||||
import Badge from './badge.vue';
|
import Badge from './badge.vue';
|
||||||
|
|
||||||
|
@ -11,7 +10,6 @@ export default {
|
||||||
components: {
|
components: {
|
||||||
Badge,
|
Badge,
|
||||||
Icon,
|
Icon,
|
||||||
LoadingIcon,
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
badge: {
|
badge: {
|
||||||
|
@ -79,7 +77,7 @@ export default {
|
||||||
name="remove"
|
name="remove"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
<loading-icon
|
<gl-loading-icon
|
||||||
v-show="badge.isDeleting"
|
v-show="badge.isDeleting"
|
||||||
:inline="true"
|
:inline="true"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
import './autosize';
|
import './autosize';
|
||||||
import './bind_in_out';
|
import './bind_in_out';
|
||||||
import './markdown/render_gfm';
|
import './markdown/render_gfm';
|
||||||
|
import initGFMInput from './markdown/gfm_auto_complete';
|
||||||
import initCopyAsGFM from './markdown/copy_as_gfm';
|
import initCopyAsGFM from './markdown/copy_as_gfm';
|
||||||
import initCopyToClipboard from './copy_to_clipboard';
|
import initCopyToClipboard from './copy_to_clipboard';
|
||||||
import './details_behavior';
|
import './details_behavior';
|
||||||
import installGlEmojiElement from './gl_emoji';
|
import installGlEmojiElement from './gl_emoji';
|
||||||
import './quick_submit';
|
import './quick_submit';
|
||||||
import './requires_input';
|
import './requires_input';
|
||||||
|
import initPageShortcuts from './shortcuts';
|
||||||
import './toggler_behavior';
|
import './toggler_behavior';
|
||||||
import '../preview_markdown';
|
import './preview_markdown';
|
||||||
|
|
||||||
installGlEmojiElement();
|
installGlEmojiElement();
|
||||||
|
initGFMInput();
|
||||||
initCopyAsGFM();
|
initCopyAsGFM();
|
||||||
initCopyToClipboard();
|
initCopyToClipboard();
|
||||||
|
initPageShortcuts();
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import $ from 'jquery';
|
||||||
|
import { convertPermissionToBoolean } from '~/lib/utils/common_utils';
|
||||||
|
import GfmAutoComplete from '~/gfm_auto_complete';
|
||||||
|
|
||||||
|
export default function initGFMInput() {
|
||||||
|
$('.js-gfm-input:not(.js-vue-textarea)').each((i, el) => {
|
||||||
|
const gfm = new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources);
|
||||||
|
const enableGFM = convertPermissionToBoolean(el.dataset.supportsAutocomplete);
|
||||||
|
|
||||||
|
gfm.setup($(el), {
|
||||||
|
emojis: true,
|
||||||
|
members: enableGFM,
|
||||||
|
issues: enableGFM,
|
||||||
|
milestones: enableGFM,
|
||||||
|
mergeRequests: enableGFM,
|
||||||
|
labels: enableGFM,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
/**
|
||||||
|
* Highlights the current user in existing elements with a user ID data attribute.
|
||||||
|
*
|
||||||
|
* @param elements DOM elements that represent user mentions
|
||||||
|
*/
|
||||||
|
export default function highlightCurrentUser(elements) {
|
||||||
|
const currentUserId = gon && gon.current_user_id;
|
||||||
|
if (!currentUserId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
elements.forEach(element => {
|
||||||
|
if (parseInt(element.dataset.user, 10) === currentUserId) {
|
||||||
|
element.classList.add('current-user');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -2,8 +2,9 @@ import $ from 'jquery';
|
||||||
import syntaxHighlight from '~/syntax_highlight';
|
import syntaxHighlight from '~/syntax_highlight';
|
||||||
import renderMath from './render_math';
|
import renderMath from './render_math';
|
||||||
import renderMermaid from './render_mermaid';
|
import renderMermaid from './render_mermaid';
|
||||||
|
import highlightCurrentUser from './highlight_current_user';
|
||||||
|
|
||||||
// Render Gitlab flavoured Markdown
|
// Render GitLab flavoured Markdown
|
||||||
//
|
//
|
||||||
// Delegates to syntax highlight and render math & mermaid diagrams.
|
// Delegates to syntax highlight and render math & mermaid diagrams.
|
||||||
//
|
//
|
||||||
|
@ -11,6 +12,7 @@ $.fn.renderGFM = function renderGFM() {
|
||||||
syntaxHighlight(this.find('.js-syntax-highlight'));
|
syntaxHighlight(this.find('.js-syntax-highlight'));
|
||||||
renderMath(this.find('.js-render-math'));
|
renderMath(this.find('.js-render-math'));
|
||||||
renderMermaid(this.find('.js-render-mermaid'));
|
renderMermaid(this.find('.js-render-mermaid'));
|
||||||
|
highlightCurrentUser(this.find('.gfm-project_member').get());
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
35
app/assets/javascripts/behaviors/shortcuts.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import Shortcuts from './shortcuts/shortcuts';
|
||||||
|
|
||||||
|
export default function initPageShortcuts() {
|
||||||
|
const { page } = document.body.dataset;
|
||||||
|
const pagesWithCustomShortcuts = [
|
||||||
|
'projects:activity',
|
||||||
|
'projects:artifacts:browse',
|
||||||
|
'projects:artifacts:file',
|
||||||
|
'projects:blame:show',
|
||||||
|
'projects:blob:show',
|
||||||
|
'projects:commit:show',
|
||||||
|
'projects:commits:show',
|
||||||
|
'projects:find_file:show',
|
||||||
|
'projects:issues:edit',
|
||||||
|
'projects:issues:index',
|
||||||
|
'projects:issues:new',
|
||||||
|
'projects:issues:show',
|
||||||
|
'projects:merge_requests:creations:diffs',
|
||||||
|
'projects:merge_requests:creations:new',
|
||||||
|
'projects:merge_requests:edit',
|
||||||
|
'projects:merge_requests:index',
|
||||||
|
'projects:merge_requests:show',
|
||||||
|
'projects:network:show',
|
||||||
|
'projects:show',
|
||||||
|
'projects:tree:show',
|
||||||
|
'groups:show',
|
||||||
|
];
|
||||||
|
|
||||||
|
// the pages above have their own shortcuts sub-classes instantiated elsewhere
|
||||||
|
// TODO: replace this whitelist with something more automated/maintainable
|
||||||
|
if (page && !pagesWithCustomShortcuts.includes(page)) {
|
||||||
|
return new Shortcuts();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
import Mousetrap from 'mousetrap';
|
import Mousetrap from 'mousetrap';
|
||||||
import axios from './lib/utils/axios_utils';
|
import axios from '../../lib/utils/axios_utils';
|
||||||
import { refreshCurrentPage, visitUrl } from './lib/utils/url_utility';
|
import { refreshCurrentPage, visitUrl } from '../../lib/utils/url_utility';
|
||||||
import findAndFollowLink from './shortcuts_dashboard_navigation';
|
import findAndFollowLink from '../../lib/utils/navigation_utility';
|
||||||
|
|
||||||
const defaultStopCallback = Mousetrap.stopCallback;
|
const defaultStopCallback = Mousetrap.stopCallback;
|
||||||
Mousetrap.stopCallback = (e, element, combo) => {
|
Mousetrap.stopCallback = (e, element, combo) => {
|
|
@ -1,5 +1,5 @@
|
||||||
import Mousetrap from 'mousetrap';
|
import Mousetrap from 'mousetrap';
|
||||||
import { getLocationHash, visitUrl } from './lib/utils/url_utility';
|
import { getLocationHash, visitUrl } from '../../lib/utils/url_utility';
|
||||||
import Shortcuts from './shortcuts';
|
import Shortcuts from './shortcuts';
|
||||||
|
|
||||||
const defaults = {
|
const defaults = {
|
|
@ -1,9 +1,9 @@
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import Mousetrap from 'mousetrap';
|
import Mousetrap from 'mousetrap';
|
||||||
import _ from 'underscore';
|
import _ from 'underscore';
|
||||||
import Sidebar from './right_sidebar';
|
import Sidebar from '../../right_sidebar';
|
||||||
import Shortcuts from './shortcuts';
|
import Shortcuts from './shortcuts';
|
||||||
import { CopyAsGFM } from './behaviors/markdown/copy_as_gfm';
|
import { CopyAsGFM } from '../markdown/copy_as_gfm';
|
||||||
|
|
||||||
export default class ShortcutsIssuable extends Shortcuts {
|
export default class ShortcutsIssuable extends Shortcuts {
|
||||||
constructor(isMergeRequest) {
|
constructor(isMergeRequest) {
|
|
@ -1,5 +1,5 @@
|
||||||
import Mousetrap from 'mousetrap';
|
import Mousetrap from 'mousetrap';
|
||||||
import findAndFollowLink from './shortcuts_dashboard_navigation';
|
import findAndFollowLink from '../../lib/utils/navigation_utility';
|
||||||
import Shortcuts from './shortcuts';
|
import Shortcuts from './shortcuts';
|
||||||
|
|
||||||
export default class ShortcutsNavigation extends Shortcuts {
|
export default class ShortcutsNavigation extends Shortcuts {
|
|
@ -1,6 +1,6 @@
|
||||||
import Mousetrap from 'mousetrap';
|
import Mousetrap from 'mousetrap';
|
||||||
import ShortcutsNavigation from './shortcuts_navigation';
|
import ShortcutsNavigation from './shortcuts_navigation';
|
||||||
import findAndFollowLink from './shortcuts_dashboard_navigation';
|
import findAndFollowLink from '../../lib/utils/navigation_utility';
|
||||||
|
|
||||||
export default class ShortcutsWiki extends ShortcutsNavigation {
|
export default class ShortcutsWiki extends ShortcutsNavigation {
|
||||||
constructor() {
|
constructor() {
|
|
@ -29,12 +29,12 @@ export default class Renderer {
|
||||||
|
|
||||||
this.scene.add(this.camera);
|
this.scene.add(this.camera);
|
||||||
|
|
||||||
// Setup the viewer
|
// Set up the viewer
|
||||||
this.setupRenderer();
|
this.setupRenderer();
|
||||||
this.setupGrid();
|
this.setupGrid();
|
||||||
this.setupLight();
|
this.setupLight();
|
||||||
|
|
||||||
// Setup OrbitControls
|
// Set up OrbitControls
|
||||||
this.controls = new OrbitControls(
|
this.controls = new OrbitControls(
|
||||||
this.camera,
|
this.camera,
|
||||||
this.renderer.domElement,
|
this.renderer.domElement,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* eslint-disable class-methods-use-this */
|
import Api from '~/api';
|
||||||
|
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import Flash from '../flash';
|
import Flash from '../flash';
|
||||||
|
@ -9,9 +9,10 @@ import GitignoreSelector from './template_selectors/gitignore_selector';
|
||||||
import LicenseSelector from './template_selectors/license_selector';
|
import LicenseSelector from './template_selectors/license_selector';
|
||||||
|
|
||||||
export default class FileTemplateMediator {
|
export default class FileTemplateMediator {
|
||||||
constructor({ editor, currentAction }) {
|
constructor({ editor, currentAction, projectId }) {
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
this.currentAction = currentAction;
|
this.currentAction = currentAction;
|
||||||
|
this.projectId = projectId;
|
||||||
|
|
||||||
this.initTemplateSelectors();
|
this.initTemplateSelectors();
|
||||||
this.initTemplateTypeSelector();
|
this.initTemplateTypeSelector();
|
||||||
|
@ -33,15 +34,14 @@ export default class FileTemplateMediator {
|
||||||
initTemplateTypeSelector() {
|
initTemplateTypeSelector() {
|
||||||
this.typeSelector = new FileTemplateTypeSelector({
|
this.typeSelector = new FileTemplateTypeSelector({
|
||||||
mediator: this,
|
mediator: this,
|
||||||
dropdownData: this.templateSelectors
|
dropdownData: this.templateSelectors.map(templateSelector => {
|
||||||
.map((templateSelector) => {
|
const cfg = templateSelector.config;
|
||||||
const cfg = templateSelector.config;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: cfg.name,
|
name: cfg.name,
|
||||||
key: cfg.key,
|
key: cfg.key,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ export default class FileTemplateMediator {
|
||||||
}
|
}
|
||||||
|
|
||||||
listenForPreviewMode() {
|
listenForPreviewMode() {
|
||||||
this.$navLinks.on('click', 'a', (e) => {
|
this.$navLinks.on('click', 'a', e => {
|
||||||
const urlPieces = e.target.href.split('#');
|
const urlPieces = e.target.href.split('#');
|
||||||
const hash = urlPieces[1];
|
const hash = urlPieces[1];
|
||||||
if (hash === 'preview') {
|
if (hash === 'preview') {
|
||||||
|
@ -105,7 +105,7 @@ export default class FileTemplateMediator {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.templateSelectors.forEach((selector) => {
|
this.templateSelectors.forEach(selector => {
|
||||||
if (selector.config.key === item.key) {
|
if (selector.config.key === item.key) {
|
||||||
selector.show();
|
selector.show();
|
||||||
} else {
|
} else {
|
||||||
|
@ -126,8 +126,8 @@ export default class FileTemplateMediator {
|
||||||
selector.renderLoading();
|
selector.renderLoading();
|
||||||
// in case undo menu is already already there
|
// in case undo menu is already already there
|
||||||
this.destroyUndoMenu();
|
this.destroyUndoMenu();
|
||||||
this.fetchFileTemplate(selector.config.endpoint, query, data)
|
this.fetchFileTemplate(selector.config.type, query, data)
|
||||||
.then((file) => {
|
.then(file => {
|
||||||
this.showUndoMenu();
|
this.showUndoMenu();
|
||||||
this.setEditorContent(file);
|
this.setEditorContent(file);
|
||||||
this.setFilename(selector.config.name);
|
this.setFilename(selector.config.name);
|
||||||
|
@ -138,7 +138,7 @@ export default class FileTemplateMediator {
|
||||||
|
|
||||||
displayMatchedTemplateSelector() {
|
displayMatchedTemplateSelector() {
|
||||||
const currentInput = this.getFilename();
|
const currentInput = this.getFilename();
|
||||||
this.templateSelectors.forEach((selector) => {
|
this.templateSelectors.forEach(selector => {
|
||||||
const match = selector.config.pattern.test(currentInput);
|
const match = selector.config.pattern.test(currentInput);
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
|
@ -149,15 +149,11 @@ export default class FileTemplateMediator {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchFileTemplate(apiCall, query, data) {
|
fetchFileTemplate(type, query, data = {}) {
|
||||||
return new Promise((resolve) => {
|
return new Promise(resolve => {
|
||||||
const resolveFile = file => resolve(file);
|
const resolveFile = file => resolve(file);
|
||||||
|
|
||||||
if (!data) {
|
Api.projectTemplate(this.projectId, type, query, data, resolveFile);
|
||||||
apiCall(query, resolveFile);
|
|
||||||
} else {
|
|
||||||
apiCall(query, data, resolveFile);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,9 +66,6 @@ export default class TemplateSelector {
|
||||||
// be added by all subclasses.
|
// be added by all subclasses.
|
||||||
}
|
}
|
||||||
|
|
||||||
// To be implemented on the extending class
|
|
||||||
// e.g. Api.gitlabCiYml(query.name, file => this.setEditorContent(file));
|
|
||||||
|
|
||||||
setEditorContent(file, { skipFocus } = {}) {
|
setEditorContent(file, { skipFocus } = {}) {
|
||||||
if (!file) return;
|
if (!file) return;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import Api from '../../api';
|
|
||||||
|
|
||||||
import FileTemplateSelector from '../file_template_selector';
|
import FileTemplateSelector from '../file_template_selector';
|
||||||
|
|
||||||
export default class BlobCiYamlSelector extends FileTemplateSelector {
|
export default class BlobCiYamlSelector extends FileTemplateSelector {
|
||||||
|
@ -9,7 +7,7 @@ export default class BlobCiYamlSelector extends FileTemplateSelector {
|
||||||
key: 'gitlab-ci-yaml',
|
key: 'gitlab-ci-yaml',
|
||||||
name: '.gitlab-ci.yml',
|
name: '.gitlab-ci.yml',
|
||||||
pattern: /(.gitlab-ci.yml)/,
|
pattern: /(.gitlab-ci.yml)/,
|
||||||
endpoint: Api.gitlabCiYml,
|
type: 'gitlab_ci_ymls',
|
||||||
dropdown: '.js-gitlab-ci-yml-selector',
|
dropdown: '.js-gitlab-ci-yml-selector',
|
||||||
wrapper: '.js-gitlab-ci-yml-selector-wrap',
|
wrapper: '.js-gitlab-ci-yml-selector-wrap',
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import Api from '../../api';
|
|
||||||
|
|
||||||
import FileTemplateSelector from '../file_template_selector';
|
import FileTemplateSelector from '../file_template_selector';
|
||||||
|
|
||||||
export default class DockerfileSelector extends FileTemplateSelector {
|
export default class DockerfileSelector extends FileTemplateSelector {
|
||||||
|
@ -9,7 +7,7 @@ export default class DockerfileSelector extends FileTemplateSelector {
|
||||||
key: 'dockerfile',
|
key: 'dockerfile',
|
||||||
name: 'Dockerfile',
|
name: 'Dockerfile',
|
||||||
pattern: /(Dockerfile)/,
|
pattern: /(Dockerfile)/,
|
||||||
endpoint: Api.dockerfileYml,
|
type: 'dockerfiles',
|
||||||
dropdown: '.js-dockerfile-selector',
|
dropdown: '.js-dockerfile-selector',
|
||||||
wrapper: '.js-dockerfile-selector-wrap',
|
wrapper: '.js-dockerfile-selector-wrap',
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import Api from '../../api';
|
|
||||||
|
|
||||||
import FileTemplateSelector from '../file_template_selector';
|
import FileTemplateSelector from '../file_template_selector';
|
||||||
|
|
||||||
export default class BlobGitignoreSelector extends FileTemplateSelector {
|
export default class BlobGitignoreSelector extends FileTemplateSelector {
|
||||||
|
@ -9,7 +7,7 @@ export default class BlobGitignoreSelector extends FileTemplateSelector {
|
||||||
key: 'gitignore',
|
key: 'gitignore',
|
||||||
name: '.gitignore',
|
name: '.gitignore',
|
||||||
pattern: /(.gitignore)/,
|
pattern: /(.gitignore)/,
|
||||||
endpoint: Api.gitignoreText,
|
type: 'gitignores',
|
||||||
dropdown: '.js-gitignore-selector',
|
dropdown: '.js-gitignore-selector',
|
||||||
wrapper: '.js-gitignore-selector-wrap',
|
wrapper: '.js-gitignore-selector-wrap',
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import Api from '../../api';
|
|
||||||
|
|
||||||
import FileTemplateSelector from '../file_template_selector';
|
import FileTemplateSelector from '../file_template_selector';
|
||||||
|
|
||||||
export default class BlobLicenseSelector extends FileTemplateSelector {
|
export default class BlobLicenseSelector extends FileTemplateSelector {
|
||||||
|
@ -9,7 +7,7 @@ export default class BlobLicenseSelector extends FileTemplateSelector {
|
||||||
key: 'license',
|
key: 'license',
|
||||||
name: 'LICENSE',
|
name: 'LICENSE',
|
||||||
pattern: /^(.+\/)?(licen[sc]e|copying)($|\.)/i,
|
pattern: /^(.+\/)?(licen[sc]e|copying)($|\.)/i,
|
||||||
endpoint: Api.licenseText,
|
type: 'licenses',
|
||||||
dropdown: '.js-license-selector',
|
dropdown: '.js-license-selector',
|
||||||
wrapper: '.js-license-selector-wrap',
|
wrapper: '.js-license-selector-wrap',
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,8 +15,9 @@ export default () => {
|
||||||
const assetsPath = editBlobForm.data('assetsPrefix');
|
const assetsPath = editBlobForm.data('assetsPrefix');
|
||||||
const blobLanguage = editBlobForm.data('blobLanguage');
|
const blobLanguage = editBlobForm.data('blobLanguage');
|
||||||
const currentAction = $('.js-file-title').data('currentAction');
|
const currentAction = $('.js-file-title').data('currentAction');
|
||||||
|
const projectId = editBlobForm.data('project-id');
|
||||||
|
|
||||||
new EditBlob(`${urlRoot}${assetsPath}`, blobLanguage, currentAction);
|
new EditBlob(`${urlRoot}${assetsPath}`, blobLanguage, currentAction, projectId);
|
||||||
new NewCommitForm(editBlobForm);
|
new NewCommitForm(editBlobForm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,11 @@ import { __ } from '~/locale';
|
||||||
import TemplateSelectorMediator from '../blob/file_template_mediator';
|
import TemplateSelectorMediator from '../blob/file_template_mediator';
|
||||||
|
|
||||||
export default class EditBlob {
|
export default class EditBlob {
|
||||||
constructor(assetsPath, aceMode, currentAction) {
|
constructor(assetsPath, aceMode, currentAction, projectId) {
|
||||||
this.configureAceEditor(aceMode, assetsPath);
|
this.configureAceEditor(aceMode, assetsPath);
|
||||||
this.initModePanesAndLinks();
|
this.initModePanesAndLinks();
|
||||||
this.initSoftWrap();
|
this.initSoftWrap();
|
||||||
this.initFileSelectors(currentAction);
|
this.initFileSelectors(currentAction, projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
configureAceEditor(aceMode, assetsPath) {
|
configureAceEditor(aceMode, assetsPath) {
|
||||||
|
@ -30,10 +30,11 @@ export default class EditBlob {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initFileSelectors(currentAction) {
|
initFileSelectors(currentAction, projectId) {
|
||||||
this.fileTemplateMediator = new TemplateSelectorMediator({
|
this.fileTemplateMediator = new TemplateSelectorMediator({
|
||||||
currentAction,
|
currentAction,
|
||||||
editor: this.editor,
|
editor: this.editor,
|
||||||
|
projectId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,14 +61,15 @@ export default class EditBlob {
|
||||||
|
|
||||||
if (paneId === '#preview') {
|
if (paneId === '#preview') {
|
||||||
this.$toggleButton.hide();
|
this.$toggleButton.hide();
|
||||||
axios.post(currentLink.data('previewUrl'), {
|
axios
|
||||||
content: this.editor.getValue(),
|
.post(currentLink.data('previewUrl'), {
|
||||||
})
|
content: this.editor.getValue(),
|
||||||
.then(({ data }) => {
|
})
|
||||||
currentPane.empty().append(data);
|
.then(({ data }) => {
|
||||||
currentPane.renderGFM();
|
currentPane.empty().append(data);
|
||||||
})
|
currentPane.renderGFM();
|
||||||
.catch(() => createFlash(__('An error occurred previewing the blob')));
|
})
|
||||||
|
.catch(() => createFlash(__('An error occurred previewing the blob')));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$toggleButton.show();
|
this.$toggleButton.show();
|
||||||
|
|
|
@ -83,7 +83,7 @@ export default {
|
||||||
right on the way to making the most of your board.
|
right on the way to making the most of your board.
|
||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
class="btn btn-create btn-inverted btn-block"
|
class="btn btn-success btn-inverted btn-block"
|
||||||
type="button"
|
type="button"
|
||||||
@click.stop="addDefaultLists">
|
@click.stop="addDefaultLists">
|
||||||
Add default lists
|
Add default lists
|
||||||
|
|
|
@ -3,7 +3,6 @@ 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';
|
||||||
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
|
|
||||||
|
|
||||||
const Store = gl.issueBoards.BoardsStore;
|
const Store = gl.issueBoards.BoardsStore;
|
||||||
|
|
||||||
|
@ -12,7 +11,6 @@ export default {
|
||||||
components: {
|
components: {
|
||||||
boardCard,
|
boardCard,
|
||||||
boardNewIssue,
|
boardNewIssue,
|
||||||
loadingIcon,
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
groupId: {
|
groupId: {
|
||||||
|
@ -217,7 +215,7 @@ export default {
|
||||||
v-if="loading"
|
v-if="loading"
|
||||||
class="board-list-loading text-center"
|
class="board-list-loading text-center"
|
||||||
aria-label="Loading issues">
|
aria-label="Loading issues">
|
||||||
<loading-icon />
|
<gl-loading-icon />
|
||||||
</div>
|
</div>
|
||||||
<board-new-issue
|
<board-new-issue
|
||||||
v-if="list.type !== 'closed' && showIssueForm"
|
v-if="list.type !== 'closed' && showIssueForm"
|
||||||
|
@ -233,19 +231,19 @@ export default {
|
||||||
<board-card
|
<board-card
|
||||||
v-for="(issue, index) in issues"
|
v-for="(issue, index) in issues"
|
||||||
ref="issue"
|
ref="issue"
|
||||||
|
:key="issue.id"
|
||||||
:index="index"
|
:index="index"
|
||||||
:list="list"
|
:list="list"
|
||||||
:issue="issue"
|
:issue="issue"
|
||||||
:issue-link-base="issueLinkBase"
|
:issue-link-base="issueLinkBase"
|
||||||
:group-id="groupId"
|
:group-id="groupId"
|
||||||
:root-path="rootPath"
|
:root-path="rootPath"
|
||||||
:disabled="disabled"
|
:disabled="disabled" />
|
||||||
:key="issue.id" />
|
|
||||||
<li
|
<li
|
||||||
v-if="showCount"
|
v-if="showCount"
|
||||||
class="board-list-count text-center"
|
class="board-list-count text-center"
|
||||||
data-issue-id="-1">
|
data-issue-id="-1">
|
||||||
<loading-icon
|
<gl-loading-icon
|
||||||
v-show="list.loadingMore"
|
v-show="list.loadingMore"
|
||||||
label="Loading more issues"
|
label="Loading more issues"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
import { Button } from '@gitlab-org/gitlab-ui';
|
||||||
import eventHub from '../eventhub';
|
import eventHub from '../eventhub';
|
||||||
import ProjectSelect from './project_select.vue';
|
import ProjectSelect from './project_select.vue';
|
||||||
import ListIssue from '../models/issue';
|
import ListIssue from '../models/issue';
|
||||||
|
@ -10,6 +11,7 @@ export default {
|
||||||
name: 'BoardNewIssue',
|
name: 'BoardNewIssue',
|
||||||
components: {
|
components: {
|
||||||
ProjectSelect,
|
ProjectSelect,
|
||||||
|
'gl-button': Button,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
groupId: {
|
groupId: {
|
||||||
|
@ -110,9 +112,9 @@ export default {
|
||||||
Title
|
Title
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
:id="list.id + '-title'"
|
||||||
ref="input"
|
ref="input"
|
||||||
v-model="title"
|
v-model="title"
|
||||||
:id="list.id + '-title'"
|
|
||||||
class="form-control"
|
class="form-control"
|
||||||
type="text"
|
type="text"
|
||||||
name="issue_title"
|
name="issue_title"
|
||||||
|
@ -123,21 +125,23 @@ export default {
|
||||||
:group-id="groupId"
|
:group-id="groupId"
|
||||||
/>
|
/>
|
||||||
<div class="clearfix prepend-top-10">
|
<div class="clearfix prepend-top-10">
|
||||||
<button
|
<gl-button
|
||||||
ref="submit-button"
|
ref="submit-button"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
class="btn btn-success float-left"
|
class="float-left"
|
||||||
|
variant="success"
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
Submit issue
|
Submit issue
|
||||||
</button>
|
</gl-button>
|
||||||
<button
|
<gl-button
|
||||||
class="btn btn-default float-right"
|
class="float-right"
|
||||||
type="button"
|
type="button"
|
||||||
|
variant="default"
|
||||||
@click="cancel"
|
@click="cancel"
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</gl-button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -149,10 +149,11 @@
|
||||||
<a
|
<a
|
||||||
:href="issue.path"
|
:href="issue.path"
|
||||||
:title="issue.title"
|
:title="issue.title"
|
||||||
class="js-no-trigger">{{ issue.title }}</a>
|
class="js-no-trigger"
|
||||||
|
@mousemove.stop>{{ issue.title }}</a>
|
||||||
<span
|
<span
|
||||||
v-if="issueId"
|
v-if="issueId"
|
||||||
class="board-card-number"
|
class="board-card-number append-right-5"
|
||||||
>
|
>
|
||||||
{{ issue.referencePath }}
|
{{ issue.referencePath }}
|
||||||
</span>
|
</span>
|
||||||
|
@ -170,8 +171,8 @@
|
||||||
tooltip-placement="bottom"
|
tooltip-placement="bottom"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
v-tooltip
|
|
||||||
v-if="shouldRenderCounter"
|
v-if="shouldRenderCounter"
|
||||||
|
v-tooltip
|
||||||
:title="assigneeCounterTooltip"
|
:title="assigneeCounterTooltip"
|
||||||
class="avatar-counter"
|
class="avatar-counter"
|
||||||
>
|
>
|
||||||
|
@ -184,10 +185,10 @@
|
||||||
class="board-card-footer"
|
class="board-card-footer"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
v-tooltip
|
|
||||||
v-for="label in issue.labels"
|
v-for="label in issue.labels"
|
||||||
v-if="showLabel(label)"
|
v-if="showLabel(label)"
|
||||||
:key="label.id"
|
:key="label.id"
|
||||||
|
v-tooltip
|
||||||
:style="labelStyle(label)"
|
:style="labelStyle(label)"
|
||||||
:title="label.description"
|
:title="label.description"
|
||||||
class="badge color-label"
|
class="badge color-label"
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
/* global ListIssue */
|
/* global ListIssue */
|
||||||
import { urlParamsToObject } from '~/lib/utils/common_utils';
|
import { urlParamsToObject } from '~/lib/utils/common_utils';
|
||||||
import loadingIcon from '~/vue_shared/components/loading_icon.vue';
|
|
||||||
import ModalHeader from './header.vue';
|
import ModalHeader from './header.vue';
|
||||||
import ModalList from './list.vue';
|
import ModalList from './list.vue';
|
||||||
import ModalFooter from './footer.vue';
|
import ModalFooter from './footer.vue';
|
||||||
|
@ -14,7 +13,6 @@
|
||||||
ModalHeader,
|
ModalHeader,
|
||||||
ModalList,
|
ModalList,
|
||||||
ModalFooter,
|
ModalFooter,
|
||||||
loadingIcon,
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
newIssuePath: {
|
newIssuePath: {
|
||||||
|
@ -167,7 +165,7 @@
|
||||||
class="add-issues-list text-center"
|
class="add-issues-list text-center"
|
||||||
>
|
>
|
||||||
<div class="add-issues-list-loading">
|
<div class="add-issues-list-loading">
|
||||||
<loading-icon />
|
<gl-loading-icon />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<modal-footer/>
|
<modal-footer/>
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { Link } from '@gitlab-org/gitlab-ui';
|
||||||
import ModalStore from '../../stores/modal_store';
|
import ModalStore from '../../stores/modal_store';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
'gl-link': Link,
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
modal: ModalStore.store,
|
modal: ModalStore.store,
|
||||||
|
@ -38,7 +42,7 @@ export default {
|
||||||
v-for="(list, i) in state.lists"
|
v-for="(list, i) in state.lists"
|
||||||
v-if="list.type == 'label'"
|
v-if="list.type == 'label'"
|
||||||
:key="i">
|
:key="i">
|
||||||
<a
|
<gl-link
|
||||||
:class="{ 'is-active': list.id == selected.id }"
|
:class="{ 'is-active': list.id == selected.id }"
|
||||||
href="#"
|
href="#"
|
||||||
role="button"
|
role="button"
|
||||||
|
@ -48,7 +52,7 @@ export default {
|
||||||
class="dropdown-label-box">
|
class="dropdown-label-box">
|
||||||
</span>
|
</span>
|
||||||
{{ list.title }}
|
{{ list.title }}
|
||||||
</a>
|
</gl-link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,14 +2,10 @@
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import _ from 'underscore';
|
import _ from 'underscore';
|
||||||
import eventHub from '../eventhub';
|
import eventHub from '../eventhub';
|
||||||
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
|
|
||||||
import Api from '../../api';
|
import Api from '../../api';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'BoardProjectSelect',
|
name: 'BoardProjectSelect',
|
||||||
components: {
|
|
||||||
loadingIcon,
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
groupId: {
|
groupId: {
|
||||||
type: Number,
|
type: Number,
|
||||||
|
@ -119,7 +115,7 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown-content"></div>
|
<div class="dropdown-content"></div>
|
||||||
<div class="dropdown-loading">
|
<div class="dropdown-loading">
|
||||||
<loading-icon />
|
<gl-loading-icon />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,7 +9,7 @@ import '~/vue_shared/models/assignee';
|
||||||
|
|
||||||
import FilteredSearchBoards from './filtered_search_boards';
|
import FilteredSearchBoards from './filtered_search_boards';
|
||||||
import eventHub from './eventhub';
|
import eventHub from './eventhub';
|
||||||
import sidebarEventHub from '~/sidebar/event_hub'; // eslint-disable-line import/first
|
import sidebarEventHub from '~/sidebar/event_hub';
|
||||||
import './models/issue';
|
import './models/issue';
|
||||||
import './models/list';
|
import './models/list';
|
||||||
import './models/milestone';
|
import './models/milestone';
|
||||||
|
@ -24,7 +24,8 @@ import './components/board';
|
||||||
import './components/board_sidebar';
|
import './components/board_sidebar';
|
||||||
import './components/new_list_dropdown';
|
import './components/new_list_dropdown';
|
||||||
import BoardAddIssuesModal from './components/modal/index.vue';
|
import BoardAddIssuesModal from './components/modal/index.vue';
|
||||||
import '~/vue_shared/vue_resource_interceptor'; // eslint-disable-line import/first
|
import '~/vue_shared/vue_resource_interceptor';
|
||||||
|
import { NavigationType } from '~/lib/utils/common_utils';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const $boardApp = document.getElementById('board-app');
|
const $boardApp = document.getElementById('board-app');
|
||||||
|
@ -32,6 +33,16 @@ export default () => {
|
||||||
|
|
||||||
window.gl = window.gl || {};
|
window.gl = window.gl || {};
|
||||||
|
|
||||||
|
// check for browser back and trigger a hard reload to circumvent browser caching.
|
||||||
|
window.addEventListener('pageshow', (event) => {
|
||||||
|
const isNavTypeBackForward = window.performance &&
|
||||||
|
window.performance.navigation.type === NavigationType.TYPE_BACK_FORWARD;
|
||||||
|
|
||||||
|
if (event.persisted || isNavTypeBackForward) {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (gl.IssueBoardsApp) {
|
if (gl.IssueBoardsApp) {
|
||||||
gl.IssueBoardsApp.$destroy(true);
|
gl.IssueBoardsApp.$destroy(true);
|
||||||
}
|
}
|
||||||
|
@ -229,7 +240,7 @@ export default () => {
|
||||||
template: `
|
template: `
|
||||||
<div class="board-extra-actions">
|
<div class="board-extra-actions">
|
||||||
<button
|
<button
|
||||||
class="btn btn-create prepend-left-10"
|
class="btn btn-success prepend-left-10"
|
||||||
type="button"
|
type="button"
|
||||||
data-placement="bottom"
|
data-placement="bottom"
|
||||||
ref="addIssuesButton"
|
ref="addIssuesButton"
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
export default function handleRevealVariables() {
|
|
||||||
$('.js-reveal-variables')
|
|
||||||
.off('click')
|
|
||||||
.on('click', function click() {
|
|
||||||
$('.js-build-variables').toggle();
|
|
||||||
$(this).hide();
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Visibility from 'visibilityjs';
|
import Visibility from 'visibilityjs';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import initDismissableCallout from '~/dismissable_callout';
|
import PersistentUserCallout from '../persistent_user_callout';
|
||||||
import { s__, sprintf } from '../locale';
|
import { s__, sprintf } from '../locale';
|
||||||
import Flash from '../flash';
|
import Flash from '../flash';
|
||||||
import Poll from '../lib/utils/poll';
|
import Poll from '../lib/utils/poll';
|
||||||
|
@ -62,7 +62,7 @@ export default class Clusters {
|
||||||
this.showTokenButton = document.querySelector('.js-show-cluster-token');
|
this.showTokenButton = document.querySelector('.js-show-cluster-token');
|
||||||
this.tokenField = document.querySelector('.js-cluster-token');
|
this.tokenField = document.querySelector('.js-cluster-token');
|
||||||
|
|
||||||
initDismissableCallout('.js-cluster-security-warning');
|
Clusters.initDismissableCallout();
|
||||||
initSettingsPanels();
|
initSettingsPanels();
|
||||||
setupToggleButtons(document.querySelector('.js-cluster-enable-toggle-area'));
|
setupToggleButtons(document.querySelector('.js-cluster-enable-toggle-area'));
|
||||||
this.initApplications();
|
this.initApplications();
|
||||||
|
@ -105,6 +105,12 @@ export default class Clusters {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static initDismissableCallout() {
|
||||||
|
const callout = document.querySelector('.js-cluster-security-warning');
|
||||||
|
|
||||||
|
if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
|
||||||
|
}
|
||||||
|
|
||||||
addListeners() {
|
addListeners() {
|
||||||
if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken);
|
if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken);
|
||||||
eventHub.$on('installApplication', this.installApplication);
|
eventHub.$on('installApplication', this.installApplication);
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
import createFlash from '~/flash';
|
import createFlash from '~/flash';
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
import setupToggleButtons from '~/toggle_buttons';
|
import setupToggleButtons from '~/toggle_buttons';
|
||||||
import initDismissableCallout from '~/dismissable_callout';
|
import PersistentUserCallout from '../persistent_user_callout';
|
||||||
|
|
||||||
import ClustersService from './services/clusters_service';
|
import ClustersService from './services/clusters_service';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const clusterList = document.querySelector('.js-clusters-list');
|
const clusterList = document.querySelector('.js-clusters-list');
|
||||||
|
|
||||||
initDismissableCallout('.gcp-signup-offer');
|
const callout = document.querySelector('.gcp-signup-offer');
|
||||||
|
if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
|
||||||
|
|
||||||
// The empty state won't have a clusterList
|
// The empty state won't have a clusterList
|
||||||
if (clusterList) {
|
if (clusterList) {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
/* eslint-disable vue/require-default-prop */
|
/* eslint-disable vue/require-default-prop */
|
||||||
import { s__, sprintf } from '../../locale';
|
import { s__, sprintf } from '../../locale';
|
||||||
import eventHub from '../event_hub';
|
import eventHub from '../event_hub';
|
||||||
|
import identicon from '../../vue_shared/components/identicon.vue';
|
||||||
import loadingButton from '../../vue_shared/components/loading_button.vue';
|
import loadingButton from '../../vue_shared/components/loading_button.vue';
|
||||||
import {
|
import {
|
||||||
APPLICATION_STATUS,
|
APPLICATION_STATUS,
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
loadingButton,
|
loadingButton,
|
||||||
|
identicon,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
id: {
|
id: {
|
||||||
|
@ -31,6 +33,16 @@
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
|
logoUrl: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
status: {
|
status: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
|
@ -60,6 +72,18 @@
|
||||||
isKnownStatus() {
|
isKnownStatus() {
|
||||||
return Object.values(APPLICATION_STATUS).includes(this.status);
|
return Object.values(APPLICATION_STATUS).includes(this.status);
|
||||||
},
|
},
|
||||||
|
isInstalled() {
|
||||||
|
return (
|
||||||
|
this.status === APPLICATION_STATUS.INSTALLED || this.status === APPLICATION_STATUS.UPDATED
|
||||||
|
);
|
||||||
|
},
|
||||||
|
hasLogo() {
|
||||||
|
return !!this.logoUrl;
|
||||||
|
},
|
||||||
|
identiconId() {
|
||||||
|
// generate a deterministic integer id for the identicon background
|
||||||
|
return this.id.charCodeAt(0);
|
||||||
|
},
|
||||||
rowJsClass() {
|
rowJsClass() {
|
||||||
return `js-cluster-application-row-${this.id}`;
|
return `js-cluster-application-row-${this.id}`;
|
||||||
},
|
},
|
||||||
|
@ -128,73 +152,61 @@
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
:class="rowJsClass"
|
:class="[
|
||||||
class="gl-responsive-table-row gl-responsive-table-row-col-span"
|
rowJsClass,
|
||||||
|
isInstalled && 'cluster-application-installed',
|
||||||
|
disabled && 'cluster-application-disabled'
|
||||||
|
]"
|
||||||
|
class="cluster-application-row gl-responsive-table-row gl-responsive-table-row-col-span"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="gl-responsive-table-row-layout"
|
class="gl-responsive-table-row-layout"
|
||||||
role="row"
|
role="row"
|
||||||
>
|
>
|
||||||
<a
|
|
||||||
v-if="titleLink"
|
|
||||||
:href="titleLink"
|
|
||||||
target="blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
role="gridcell"
|
|
||||||
class="table-section section-15 section-align-top js-cluster-application-title"
|
|
||||||
>
|
|
||||||
{{ title }}
|
|
||||||
</a>
|
|
||||||
<span
|
|
||||||
v-else
|
|
||||||
class="table-section section-15 section-align-top js-cluster-application-title"
|
|
||||||
>
|
|
||||||
{{ title }}
|
|
||||||
</span>
|
|
||||||
<div
|
<div
|
||||||
class="table-section section-wrap"
|
class="table-section append-right-8 section-align-top"
|
||||||
role="gridcell"
|
role="gridcell"
|
||||||
>
|
>
|
||||||
<slot name="description"></slot>
|
<img
|
||||||
|
v-if="hasLogo"
|
||||||
|
:src="logoUrl"
|
||||||
|
:alt="`${title} logo`"
|
||||||
|
class="cluster-application-logo avatar s40"
|
||||||
|
/>
|
||||||
|
<identicon
|
||||||
|
v-else
|
||||||
|
:entity-id="identiconId"
|
||||||
|
:entity-name="title"
|
||||||
|
size-class="s40"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
:class="{ 'section-20': showManageButton, 'section-15': !showManageButton }"
|
class="table-section cluster-application-description section-wrap"
|
||||||
class="table-section table-button-footer section-align-top"
|
|
||||||
role="gridcell"
|
role="gridcell"
|
||||||
>
|
>
|
||||||
<div
|
<strong>
|
||||||
v-if="showManageButton"
|
|
||||||
class="btn-group table-action-buttons"
|
|
||||||
>
|
|
||||||
<a
|
<a
|
||||||
:href="manageLink"
|
v-if="titleLink"
|
||||||
class="btn"
|
:href="titleLink"
|
||||||
|
target="blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="js-cluster-application-title"
|
||||||
>
|
>
|
||||||
{{ manageButtonLabel }}
|
{{ title }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
<span
|
||||||
<div class="btn-group table-action-buttons">
|
v-else
|
||||||
<loading-button
|
class="js-cluster-application-title"
|
||||||
:loading="installButtonLoading"
|
>
|
||||||
:disabled="installButtonDisabled"
|
{{ title }}
|
||||||
:label="installButtonLabel"
|
</span>
|
||||||
class="js-cluster-application-install-button"
|
</strong>
|
||||||
@click="installClicked"
|
<slot name="description"></slot>
|
||||||
/>
|
<div
|
||||||
</div>
|
v-if="hasError || isUnknownStatus"
|
||||||
</div>
|
class="cluster-application-error text-danger prepend-top-10"
|
||||||
</div>
|
>
|
||||||
<div
|
<p class="js-cluster-application-general-error-message append-bottom-0">
|
||||||
v-if="hasError || isUnknownStatus"
|
|
||||||
class="gl-responsive-table-row-layout"
|
|
||||||
role="row"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="alert alert-danger alert-block append-bottom-0 clusters-error-alert"
|
|
||||||
role="gridcell"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<p class="js-cluster-application-general-error-message">
|
|
||||||
{{ generalErrorDescription }}
|
{{ generalErrorDescription }}
|
||||||
</p>
|
</p>
|
||||||
<ul v-if="statusReason || requestReason">
|
<ul v-if="statusReason || requestReason">
|
||||||
|
@ -213,6 +225,33 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
:class="{ 'section-25': showManageButton, 'section-15': !showManageButton }"
|
||||||
|
class="table-section table-button-footer section-align-top"
|
||||||
|
role="gridcell"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="showManageButton"
|
||||||
|
class="btn-group table-action-buttons"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
:href="manageLink"
|
||||||
|
:class="{ disabled: disabled }"
|
||||||
|
class="btn"
|
||||||
|
>
|
||||||
|
{{ manageButtonLabel }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group table-action-buttons">
|
||||||
|
<loading-button
|
||||||
|
:loading="installButtonLoading"
|
||||||
|
:disabled="disabled || installButtonDisabled"
|
||||||
|
:label="installButtonLabel"
|
||||||
|
class="js-cluster-application-install-button"
|
||||||
|
@click="installClicked"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
<script>
|
<script>
|
||||||
import _ from 'underscore';
|
import _ from 'underscore';
|
||||||
|
import helmInstallIllustration from '@gitlab-org/gitlab-svgs/illustrations/kubernetes-installation.svg';
|
||||||
|
import elasticsearchLogo from 'images/cluster_app_logos/elasticsearch.png';
|
||||||
|
import gitlabLogo from 'images/cluster_app_logos/gitlab.png';
|
||||||
|
import helmLogo from 'images/cluster_app_logos/helm.png';
|
||||||
|
import jeagerLogo from 'images/cluster_app_logos/jeager.png';
|
||||||
|
import jupyterhubLogo from 'images/cluster_app_logos/jupyterhub.png';
|
||||||
|
import kubernetesLogo from 'images/cluster_app_logos/kubernetes.png';
|
||||||
|
import meltanoLogo from 'images/cluster_app_logos/meltano.png';
|
||||||
|
import prometheusLogo from 'images/cluster_app_logos/prometheus.png';
|
||||||
import { s__, sprintf } from '../../locale';
|
import { s__, sprintf } from '../../locale';
|
||||||
import applicationRow from './application_row.vue';
|
import applicationRow from './application_row.vue';
|
||||||
import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
|
import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
|
||||||
|
@ -37,21 +46,21 @@ export default {
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
data: () => ({
|
||||||
|
elasticsearchLogo,
|
||||||
|
gitlabLogo,
|
||||||
|
helmLogo,
|
||||||
|
jeagerLogo,
|
||||||
|
jupyterhubLogo,
|
||||||
|
kubernetesLogo,
|
||||||
|
meltanoLogo,
|
||||||
|
prometheusLogo,
|
||||||
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
generalApplicationDescription() {
|
helmInstalled() {
|
||||||
return sprintf(
|
return (
|
||||||
_.escape(
|
this.applications.helm.status === APPLICATION_STATUS.INSTALLED ||
|
||||||
s__(
|
this.applications.helm.status === APPLICATION_STATUS.UPDATED
|
||||||
`ClusterIntegration|Install applications on your Kubernetes cluster.
|
|
||||||
Read more about %{helpLink}`,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
{
|
|
||||||
helpLink: `<a href="${this.helpPath}">
|
|
||||||
${_.escape(s__('ClusterIntegration|installing applications'))}
|
|
||||||
</a>`,
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
ingressId() {
|
ingressId() {
|
||||||
|
@ -128,224 +137,240 @@ export default {
|
||||||
return this.applications.jupyter.hostname;
|
return this.applications.jupyter.hostname;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
this.helmInstallIllustration = helmInstallIllustration;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section
|
<section id="cluster-applications">
|
||||||
id="cluster-applications"
|
<h4>
|
||||||
class="settings no-animate expanded"
|
{{ s__('ClusterIntegration|Applications') }}
|
||||||
>
|
</h4>
|
||||||
<div class="settings-header">
|
<p class="append-bottom-0">
|
||||||
<h4>
|
{{ s__(`ClusterIntegration|Choose which applications to install on your Kubernetes cluster.
|
||||||
{{ s__('ClusterIntegration|Applications') }}
|
Helm Tiller is required to install any of the following applications.`) }}
|
||||||
</h4>
|
<a :href="helpPath">
|
||||||
<p
|
{{ __('More information') }}
|
||||||
class="append-bottom-0"
|
</a>
|
||||||
v-html="generalApplicationDescription"
|
</p>
|
||||||
|
|
||||||
|
<div class="cluster-application-list prepend-top-10">
|
||||||
|
<application-row
|
||||||
|
id="helm"
|
||||||
|
:logo-url="helmLogo"
|
||||||
|
:title="applications.helm.title"
|
||||||
|
:status="applications.helm.status"
|
||||||
|
:status-reason="applications.helm.statusReason"
|
||||||
|
:request-status="applications.helm.requestStatus"
|
||||||
|
:request-reason="applications.helm.requestReason"
|
||||||
|
class="rounded-top"
|
||||||
|
title-link="https://docs.helm.sh/"
|
||||||
>
|
>
|
||||||
</p>
|
<div slot="description">
|
||||||
</div>
|
{{ s__(`ClusterIntegration|Helm streamlines installing
|
||||||
|
and managing Kubernetes applications.
|
||||||
<div class="settings-content">
|
Tiller runs inside of your Kubernetes Cluster,
|
||||||
<div class="append-bottom-20">
|
and manages releases of your charts.`) }}
|
||||||
<application-row
|
</div>
|
||||||
id="helm"
|
</application-row>
|
||||||
:title="applications.helm.title"
|
<div
|
||||||
:status="applications.helm.status"
|
v-show="!helmInstalled"
|
||||||
:status-reason="applications.helm.statusReason"
|
class="cluster-application-warning"
|
||||||
:request-status="applications.helm.requestStatus"
|
>
|
||||||
:request-reason="applications.helm.requestReason"
|
<div
|
||||||
title-link="https://docs.helm.sh/"
|
class="svg-container"
|
||||||
|
v-html="helmInstallIllustration"
|
||||||
>
|
>
|
||||||
<div slot="description">
|
</div>
|
||||||
{{ s__(`ClusterIntegration|Helm streamlines installing
|
{{ s__(`ClusterIntegration|You must first install Helm Tiller before
|
||||||
and managing Kubernetes applications.
|
installing the applications below`) }}
|
||||||
Tiller runs inside of your Kubernetes Cluster,
|
</div>
|
||||||
and manages releases of your charts.`) }}
|
<application-row
|
||||||
</div>
|
:id="ingressId"
|
||||||
</application-row>
|
:logo-url="kubernetesLogo"
|
||||||
<application-row
|
:title="applications.ingress.title"
|
||||||
:id="ingressId"
|
:status="applications.ingress.status"
|
||||||
:title="applications.ingress.title"
|
:status-reason="applications.ingress.statusReason"
|
||||||
:status="applications.ingress.status"
|
:request-status="applications.ingress.requestStatus"
|
||||||
:status-reason="applications.ingress.statusReason"
|
:request-reason="applications.ingress.requestReason"
|
||||||
:request-status="applications.ingress.requestStatus"
|
:disabled="!helmInstalled"
|
||||||
:request-reason="applications.ingress.requestReason"
|
title-link="https://kubernetes.io/docs/concepts/services-networking/ingress/"
|
||||||
title-link="https://kubernetes.io/docs/concepts/services-networking/ingress/"
|
>
|
||||||
>
|
<div slot="description">
|
||||||
<div slot="description">
|
<p>
|
||||||
<p>
|
{{ s__(`ClusterIntegration|Ingress gives you a way to route
|
||||||
{{ s__(`ClusterIntegration|Ingress gives you a way to route
|
requests to services based on the request host or path,
|
||||||
requests to services based on the request host or path,
|
centralizing a number of services into a single entrypoint.`) }}
|
||||||
centralizing a number of services into a single entrypoint.`) }}
|
</p>
|
||||||
</p>
|
|
||||||
|
|
||||||
<template v-if="ingressInstalled">
|
<template v-if="ingressInstalled">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="ingress-ip-address">
|
<label for="ingress-ip-address">
|
||||||
{{ s__('ClusterIntegration|Ingress IP Address') }}
|
{{ s__('ClusterIntegration|Ingress IP Address') }}
|
||||||
</label>
|
</label>
|
||||||
<div
|
<div
|
||||||
v-if="ingressExternalIp"
|
v-if="ingressExternalIp"
|
||||||
class="input-group"
|
class="input-group"
|
||||||
>
|
>
|
||||||
<input
|
|
||||||
id="ingress-ip-address"
|
|
||||||
:value="ingressExternalIp"
|
|
||||||
type="text"
|
|
||||||
class="form-control js-ip-address"
|
|
||||||
readonly
|
|
||||||
/>
|
|
||||||
<span class="input-group-append">
|
|
||||||
<clipboard-button
|
|
||||||
:text="ingressExternalIp"
|
|
||||||
:title="s__('ClusterIntegration|Copy Ingress IP Address to clipboard')"
|
|
||||||
class="input-group-text js-clipboard-btn"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<input
|
<input
|
||||||
v-else
|
id="ingress-ip-address"
|
||||||
|
:value="ingressExternalIp"
|
||||||
type="text"
|
type="text"
|
||||||
class="form-control js-ip-address"
|
class="form-control js-ip-address"
|
||||||
readonly
|
readonly
|
||||||
value="?"
|
|
||||||
/>
|
/>
|
||||||
|
<span class="input-group-append">
|
||||||
|
<clipboard-button
|
||||||
|
:text="ingressExternalIp"
|
||||||
|
:title="s__('ClusterIntegration|Copy Ingress IP Address to clipboard')"
|
||||||
|
class="input-group-text js-clipboard-btn"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<input
|
||||||
<p
|
v-else
|
||||||
v-if="!ingressExternalIp"
|
type="text"
|
||||||
class="settings-message js-no-ip-message"
|
class="form-control js-ip-address"
|
||||||
>
|
readonly
|
||||||
{{ s__(`ClusterIntegration|The IP address is in
|
value="?"
|
||||||
the process of being assigned. Please check your Kubernetes
|
/>
|
||||||
cluster or Quotas on Google Kubernetes Engine if it takes a long time.`) }}
|
|
||||||
|
|
||||||
<a
|
|
||||||
:href="ingressHelpPath"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{{ __('More information') }}
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
{{ s__(`ClusterIntegration|Point a wildcard DNS to this
|
|
||||||
generated IP address in order to access
|
|
||||||
your application after it has been deployed.`) }}
|
|
||||||
<a
|
|
||||||
:href="ingressDnsHelpPath"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{{ __('More information') }}
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
<div
|
|
||||||
v-else
|
|
||||||
v-html="ingressDescription"
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</application-row>
|
<p
|
||||||
<application-row
|
v-if="!ingressExternalIp"
|
||||||
id="prometheus"
|
class="settings-message js-no-ip-message"
|
||||||
:title="applications.prometheus.title"
|
>
|
||||||
:manage-link="managePrometheusPath"
|
{{ s__(`ClusterIntegration|The IP address is in
|
||||||
:status="applications.prometheus.status"
|
the process of being assigned. Please check your Kubernetes
|
||||||
:status-reason="applications.prometheus.statusReason"
|
cluster or Quotas on Google Kubernetes Engine if it takes a long time.`) }}
|
||||||
:request-status="applications.prometheus.requestStatus"
|
|
||||||
:request-reason="applications.prometheus.requestReason"
|
<a
|
||||||
title-link="https://prometheus.io/docs/introduction/overview/"
|
:href="ingressHelpPath"
|
||||||
>
|
target="_blank"
|
||||||
<div
|
rel="noopener noreferrer"
|
||||||
slot="description"
|
>
|
||||||
v-html="prometheusDescription"
|
{{ __('More information') }}
|
||||||
>
|
</a>
|
||||||
</div>
|
|
||||||
</application-row>
|
|
||||||
<application-row
|
|
||||||
id="runner"
|
|
||||||
:title="applications.runner.title"
|
|
||||||
:status="applications.runner.status"
|
|
||||||
:status-reason="applications.runner.statusReason"
|
|
||||||
:request-status="applications.runner.requestStatus"
|
|
||||||
:request-reason="applications.runner.requestReason"
|
|
||||||
title-link="https://docs.gitlab.com/runner/"
|
|
||||||
>
|
|
||||||
<div slot="description">
|
|
||||||
{{ s__(`ClusterIntegration|GitLab Runner connects to this
|
|
||||||
project's repository and executes CI/CD jobs,
|
|
||||||
pushing results back and deploying,
|
|
||||||
applications to production.`) }}
|
|
||||||
</div>
|
|
||||||
</application-row>
|
|
||||||
<application-row
|
|
||||||
id="jupyter"
|
|
||||||
:title="applications.jupyter.title"
|
|
||||||
:status="applications.jupyter.status"
|
|
||||||
:status-reason="applications.jupyter.statusReason"
|
|
||||||
:request-status="applications.jupyter.requestStatus"
|
|
||||||
:request-reason="applications.jupyter.requestReason"
|
|
||||||
:install-application-request-params="{ hostname: applications.jupyter.hostname }"
|
|
||||||
title-link="https://jupyterhub.readthedocs.io/en/stable/"
|
|
||||||
>
|
|
||||||
<div slot="description">
|
|
||||||
<p>
|
|
||||||
{{ s__(`ClusterIntegration|JupyterHub, a multi-user Hub, spawns,
|
|
||||||
manages, and proxies multiple instances of the single-user
|
|
||||||
Jupyter notebook server. JupyterHub can be used to serve
|
|
||||||
notebooks to a class of students, a corporate data science group,
|
|
||||||
or a scientific research group.`) }}
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<template v-if="ingressExternalIp">
|
<p>
|
||||||
<div class="form-group">
|
{{ s__(`ClusterIntegration|Point a wildcard DNS to this
|
||||||
<label for="jupyter-hostname">
|
generated IP address in order to access
|
||||||
{{ s__('ClusterIntegration|Jupyter Hostname') }}
|
your application after it has been deployed.`) }}
|
||||||
</label>
|
<a
|
||||||
|
:href="ingressDnsHelpPath"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{{ __('More information') }}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
<div class="input-group">
|
</template>
|
||||||
<input
|
<div
|
||||||
v-model="applications.jupyter.hostname"
|
v-html="ingressDescription"
|
||||||
:readonly="jupyterInstalled"
|
>
|
||||||
type="text"
|
|
||||||
class="form-control js-hostname"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="input-group-btn"
|
|
||||||
>
|
|
||||||
<clipboard-button
|
|
||||||
:text="jupyterHostname"
|
|
||||||
:title="s__('ClusterIntegration|Copy Jupyter Hostname to clipboard')"
|
|
||||||
class="js-clipboard-btn"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p v-if="ingressInstalled">
|
|
||||||
{{ s__(`ClusterIntegration|Replace this with your own hostname if you want.
|
|
||||||
If you do so, point hostname to Ingress IP Address from above.`) }}
|
|
||||||
<a
|
|
||||||
:href="ingressDnsHelpPath"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{{ __('More information') }}
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</application-row>
|
</div>
|
||||||
<!--
|
</application-row>
|
||||||
NOTE: Don't forget to update `clusters.scss`
|
<application-row
|
||||||
min-height for this block and uncomment `application_spec` tests
|
id="prometheus"
|
||||||
-->
|
:logo-url="prometheusLogo"
|
||||||
</div>
|
:title="applications.prometheus.title"
|
||||||
|
:manage-link="managePrometheusPath"
|
||||||
|
:status="applications.prometheus.status"
|
||||||
|
:status-reason="applications.prometheus.statusReason"
|
||||||
|
:request-status="applications.prometheus.requestStatus"
|
||||||
|
:request-reason="applications.prometheus.requestReason"
|
||||||
|
:disabled="!helmInstalled"
|
||||||
|
title-link="https://prometheus.io/docs/introduction/overview/"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
slot="description"
|
||||||
|
v-html="prometheusDescription"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</application-row>
|
||||||
|
<application-row
|
||||||
|
id="runner"
|
||||||
|
:logo-url="gitlabLogo"
|
||||||
|
:title="applications.runner.title"
|
||||||
|
:status="applications.runner.status"
|
||||||
|
:status-reason="applications.runner.statusReason"
|
||||||
|
:request-status="applications.runner.requestStatus"
|
||||||
|
:request-reason="applications.runner.requestReason"
|
||||||
|
:disabled="!helmInstalled"
|
||||||
|
title-link="https://docs.gitlab.com/runner/"
|
||||||
|
>
|
||||||
|
<div slot="description">
|
||||||
|
{{ s__(`ClusterIntegration|GitLab Runner connects to this
|
||||||
|
project's repository and executes CI/CD jobs,
|
||||||
|
pushing results back and deploying,
|
||||||
|
applications to production.`) }}
|
||||||
|
</div>
|
||||||
|
</application-row>
|
||||||
|
<application-row
|
||||||
|
id="jupyter"
|
||||||
|
:logo-url="jupyterhubLogo"
|
||||||
|
:title="applications.jupyter.title"
|
||||||
|
:status="applications.jupyter.status"
|
||||||
|
:status-reason="applications.jupyter.statusReason"
|
||||||
|
:request-status="applications.jupyter.requestStatus"
|
||||||
|
:request-reason="applications.jupyter.requestReason"
|
||||||
|
:install-application-request-params="{ hostname: applications.jupyter.hostname }"
|
||||||
|
:disabled="!helmInstalled"
|
||||||
|
class="hide-bottom-border rounded-bottom"
|
||||||
|
title-link="https://jupyterhub.readthedocs.io/en/stable/"
|
||||||
|
>
|
||||||
|
<div slot="description">
|
||||||
|
<p>
|
||||||
|
{{ s__(`ClusterIntegration|JupyterHub, a multi-user Hub, spawns,
|
||||||
|
manages, and proxies multiple instances of the single-user
|
||||||
|
Jupyter notebook server. JupyterHub can be used to serve
|
||||||
|
notebooks to a class of students, a corporate data science group,
|
||||||
|
or a scientific research group.`) }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<template v-if="ingressExternalIp">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="jupyter-hostname">
|
||||||
|
{{ s__('ClusterIntegration|Jupyter Hostname') }}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="input-group">
|
||||||
|
<input
|
||||||
|
v-model="applications.jupyter.hostname"
|
||||||
|
:readonly="jupyterInstalled"
|
||||||
|
type="text"
|
||||||
|
class="form-control js-hostname"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="input-group-btn"
|
||||||
|
>
|
||||||
|
<clipboard-button
|
||||||
|
:text="jupyterHostname"
|
||||||
|
:title="s__('ClusterIntegration|Copy Jupyter Hostname to clipboard')"
|
||||||
|
class="js-clipboard-btn"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p v-if="ingressInstalled">
|
||||||
|
{{ s__(`ClusterIntegration|Replace this with your own hostname if you want.
|
||||||
|
If you do so, point hostname to Ingress IP Address from above.`) }}
|
||||||
|
<a
|
||||||
|
:href="ingressDnsHelpPath"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{{ __('More information') }}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</application-row>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -76,10 +76,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="content-list pipelines">
|
<div class="content-list pipelines">
|
||||||
|
|
||||||
<loading-icon
|
<gl-loading-icon
|
||||||
v-if="isLoading"
|
v-if="isLoading"
|
||||||
:label="s__('Pipelines|Loading Pipelines')"
|
:label="s__('Pipelines|Loading Pipelines')"
|
||||||
size="3"
|
:size="3"
|
||||||
class="prepend-top-20"
|
class="prepend-top-20"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import progressBar from '@gitlab-org/gitlab-ui/dist/components/base/progress_bar';
|
import {
|
||||||
import modal from '@gitlab-org/gitlab-ui/dist/components/base/modal';
|
Pagination,
|
||||||
|
ProgressBar,
|
||||||
|
Modal,
|
||||||
|
LoadingIcon,
|
||||||
|
ModalDirective,
|
||||||
|
TooltipDirective,
|
||||||
|
} from '@gitlab-org/gitlab-ui';
|
||||||
|
|
||||||
import dModal from '@gitlab-org/gitlab-ui/dist/directives/modal';
|
Vue.component('gl-pagination', Pagination);
|
||||||
|
Vue.component('gl-progress-bar', ProgressBar);
|
||||||
|
Vue.component('gl-ui-modal', Modal);
|
||||||
|
Vue.component('gl-loading-icon', LoadingIcon);
|
||||||
|
|
||||||
Vue.component('gl-progress-bar', progressBar);
|
Vue.directive('gl-modal', ModalDirective);
|
||||||
Vue.component('gl-ui-modal', modal);
|
Vue.directive('gl-tooltip', TooltipDirective);
|
||||||
|
|
||||||
Vue.directive('gl-modal', dModal);
|
|
||||||
|
|
|
@ -14,10 +14,10 @@ import 'core-js/es6/map';
|
||||||
import 'core-js/es6/weak-map';
|
import 'core-js/es6/weak-map';
|
||||||
|
|
||||||
// Browser polyfills
|
// Browser polyfills
|
||||||
import 'classlist-polyfill';
|
|
||||||
import 'formdata-polyfill';
|
import 'formdata-polyfill';
|
||||||
import './polyfills/custom_event';
|
import './polyfills/custom_event';
|
||||||
import './polyfills/element';
|
import './polyfills/element';
|
||||||
import './polyfills/event';
|
import './polyfills/event';
|
||||||
import './polyfills/nodelist';
|
import './polyfills/nodelist';
|
||||||
import './polyfills/request_idle_callback';
|
import './polyfills/request_idle_callback';
|
||||||
|
import './polyfills/svg';
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
Element.prototype.closest = Element.prototype.closest ||
|
// polyfill Element.classList and DOMTokenList with classList.js
|
||||||
|
import 'classlist-polyfill';
|
||||||
|
|
||||||
|
Element.prototype.closest =
|
||||||
|
Element.prototype.closest ||
|
||||||
function closest(selector, selectedElement = this) {
|
function closest(selector, selectedElement = this) {
|
||||||
if (!selectedElement) return null;
|
if (!selectedElement) return null;
|
||||||
return selectedElement.matches(selector) ?
|
return selectedElement.matches(selector)
|
||||||
selectedElement :
|
? selectedElement
|
||||||
Element.prototype.closest(selector, selectedElement.parentElement);
|
: Element.prototype.closest(selector, selectedElement.parentElement);
|
||||||
};
|
};
|
||||||
|
|
||||||
Element.prototype.matches = Element.prototype.matches ||
|
Element.prototype.matches =
|
||||||
|
Element.prototype.matches ||
|
||||||
Element.prototype.matchesSelector ||
|
Element.prototype.matchesSelector ||
|
||||||
Element.prototype.mozMatchesSelector ||
|
Element.prototype.mozMatchesSelector ||
|
||||||
Element.prototype.msMatchesSelector ||
|
Element.prototype.msMatchesSelector ||
|
||||||
|
@ -15,13 +20,15 @@ Element.prototype.matches = Element.prototype.matches ||
|
||||||
function matches(selector) {
|
function matches(selector) {
|
||||||
const elms = (this.document || this.ownerDocument).querySelectorAll(selector);
|
const elms = (this.document || this.ownerDocument).querySelectorAll(selector);
|
||||||
let i = elms.length - 1;
|
let i = elms.length - 1;
|
||||||
while (i >= 0 && elms.item(i) !== this) { i -= 1; }
|
while (i >= 0 && elms.item(i) !== this) {
|
||||||
|
i -= 1;
|
||||||
|
}
|
||||||
return i > -1;
|
return i > -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// From the polyfill on MDN, https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove#Polyfill
|
// From the polyfill on MDN, https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove#Polyfill
|
||||||
((arr) => {
|
(arr => {
|
||||||
arr.forEach((item) => {
|
arr.forEach(item => {
|
||||||
if (Object.prototype.hasOwnProperty.call(item, 'remove')) {
|
if (Object.prototype.hasOwnProperty.call(item, 'remove')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
5
app/assets/javascripts/commons/polyfills/svg.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import svg4everybody from 'svg4everybody';
|
||||||
|
|
||||||
|
// polyfill support for external SVG file references via <use xlink:href>
|
||||||
|
// @see https://css-tricks.com/svg-use-external-source/
|
||||||
|
svg4everybody();
|
|
@ -1,11 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import loadingIcon from '~/vue_shared/components/loading_icon.vue';
|
|
||||||
import eventHub from '../eventhub';
|
import eventHub from '../eventhub';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
|
||||||
loadingIcon,
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
deployKey: {
|
deployKey: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -45,7 +41,7 @@ export default {
|
||||||
class="btn"
|
class="btn"
|
||||||
@click="doAction">
|
@click="doAction">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
<loading-icon
|
<gl-loading-icon
|
||||||
v-if="isLoading"
|
v-if="isLoading"
|
||||||
:inline="true"
|
:inline="true"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { s__ } from '~/locale';
|
import { s__ } from '~/locale';
|
||||||
import Flash from '~/flash';
|
import Flash from '~/flash';
|
||||||
import LoadingIcon from '~/vue_shared/components/loading_icon.vue';
|
|
||||||
import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
|
import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
|
||||||
import eventHub from '../eventhub';
|
import eventHub from '../eventhub';
|
||||||
import DeployKeysService from '../service';
|
import DeployKeysService from '../service';
|
||||||
|
@ -11,7 +10,6 @@ import KeysPanel from './keys_panel.vue';
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
KeysPanel,
|
KeysPanel,
|
||||||
LoadingIcon,
|
|
||||||
NavigationTabs,
|
NavigationTabs,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -114,10 +112,10 @@ export default {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="append-bottom-default deploy-keys">
|
<div class="append-bottom-default deploy-keys">
|
||||||
<loading-icon
|
<gl-loading-icon
|
||||||
v-if="isLoading && !hasKeys"
|
v-if="isLoading && !hasKeys"
|
||||||
:label="s__('DeployKeys|Loading deploy keys')"
|
:label="s__('DeployKeys|Loading deploy keys')"
|
||||||
size="2"
|
:size="2"
|
||||||
/>
|
/>
|
||||||
<template v-else-if="hasKeys">
|
<template v-else-if="hasKeys">
|
||||||
<div class="top-area scrolling-tabs-container inner-page-scroll-tabs">
|
<div class="top-area scrolling-tabs-container inner-page-scroll-tabs">
|
||||||
|
|
|
@ -145,8 +145,8 @@ export default {
|
||||||
<icon :name="firstProject.can_push ? 'lock-open' : 'lock'"/>
|
<icon :name="firstProject.can_push ? 'lock-open' : 'lock'"/>
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
v-tooltip
|
|
||||||
v-if="isExpandable"
|
v-if="isExpandable"
|
||||||
|
v-tooltip
|
||||||
:title="restProjectsTooltip"
|
:title="restProjectsTooltip"
|
||||||
class="label deploy-project-label"
|
class="label deploy-project-label"
|
||||||
@click="toggleExpanded"
|
@click="toggleExpanded"
|
||||||
|
@ -154,10 +154,10 @@ export default {
|
||||||
<span>{{ restProjectsLabel }}</span>
|
<span>{{ restProjectsLabel }}</span>
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
v-tooltip
|
|
||||||
v-for="deployKeysProject in restProjects"
|
v-for="deployKeysProject in restProjects"
|
||||||
v-else-if="isExpanded"
|
v-else-if="isExpanded"
|
||||||
:key="deployKeysProject.project.full_path"
|
:key="deployKeysProject.project.full_path"
|
||||||
|
v-tooltip
|
||||||
:href="deployKeysProject.project.full_path"
|
:href="deployKeysProject.project.full_path"
|
||||||
:title="projectTooltipTitle(deployKeysProject)"
|
:title="projectTooltipTitle(deployKeysProject)"
|
||||||
class="label deploy-project-label"
|
class="label deploy-project-label"
|
||||||
|
@ -198,8 +198,8 @@ export default {
|
||||||
{{ __('Enable') }}
|
{{ __('Enable') }}
|
||||||
</action-btn>
|
</action-btn>
|
||||||
<a
|
<a
|
||||||
v-tooltip
|
|
||||||
v-if="deployKey.can_edit"
|
v-if="deployKey.can_edit"
|
||||||
|
v-tooltip
|
||||||
:href="editDeployKeyPath"
|
:href="editDeployKeyPath"
|
||||||
:title="__('Edit')"
|
:title="__('Edit')"
|
||||||
class="btn btn-default text-secondary"
|
class="btn btn-default text-secondary"
|
||||||
|
@ -208,8 +208,8 @@ export default {
|
||||||
<icon name="pencil"/>
|
<icon name="pencil"/>
|
||||||
</a>
|
</a>
|
||||||
<action-btn
|
<action-btn
|
||||||
v-tooltip
|
|
||||||
v-if="isRemovable"
|
v-if="isRemovable"
|
||||||
|
v-tooltip
|
||||||
:deploy-key="deployKey"
|
:deploy-key="deployKey"
|
||||||
:title="__('Remove')"
|
:title="__('Remove')"
|
||||||
btn-css-class="btn-danger"
|
btn-css-class="btn-danger"
|
||||||
|
@ -219,8 +219,8 @@ export default {
|
||||||
<icon name="remove"/>
|
<icon name="remove"/>
|
||||||
</action-btn>
|
</action-btn>
|
||||||
<action-btn
|
<action-btn
|
||||||
v-tooltip
|
|
||||||
v-else-if="isEnabled"
|
v-else-if="isEnabled"
|
||||||
|
v-tooltip
|
||||||
:deploy-key="deployKey"
|
:deploy-key="deployKey"
|
||||||
:title="__('Disable')"
|
:title="__('Disable')"
|
||||||
btn-css-class="btn-warning"
|
btn-css-class="btn-warning"
|
||||||
|
|
|
@ -4,23 +4,23 @@ import Icon from '~/vue_shared/components/icon.vue';
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
import createFlash from '~/flash';
|
import createFlash from '~/flash';
|
||||||
import eventHub from '../../notes/event_hub';
|
import eventHub from '../../notes/event_hub';
|
||||||
import LoadingIcon from '../../vue_shared/components/loading_icon.vue';
|
|
||||||
import CompareVersions from './compare_versions.vue';
|
import CompareVersions from './compare_versions.vue';
|
||||||
import ChangedFiles from './changed_files.vue';
|
|
||||||
import DiffFile from './diff_file.vue';
|
import DiffFile from './diff_file.vue';
|
||||||
import NoChanges from './no_changes.vue';
|
import NoChanges from './no_changes.vue';
|
||||||
import HiddenFilesWarning from './hidden_files_warning.vue';
|
import HiddenFilesWarning from './hidden_files_warning.vue';
|
||||||
|
import CommitWidget from './commit_widget.vue';
|
||||||
|
import TreeList from './tree_list.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DiffsApp',
|
name: 'DiffsApp',
|
||||||
components: {
|
components: {
|
||||||
Icon,
|
Icon,
|
||||||
LoadingIcon,
|
|
||||||
CompareVersions,
|
CompareVersions,
|
||||||
ChangedFiles,
|
|
||||||
DiffFile,
|
DiffFile,
|
||||||
NoChanges,
|
NoChanges,
|
||||||
HiddenFilesWarning,
|
HiddenFilesWarning,
|
||||||
|
CommitWidget,
|
||||||
|
TreeList,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
endpoint: {
|
endpoint: {
|
||||||
|
@ -58,6 +58,7 @@ export default {
|
||||||
plainDiffPath: state => state.diffs.plainDiffPath,
|
plainDiffPath: state => state.diffs.plainDiffPath,
|
||||||
emailPatchPath: state => state.diffs.emailPatchPath,
|
emailPatchPath: state => state.diffs.emailPatchPath,
|
||||||
}),
|
}),
|
||||||
|
...mapState('diffs', ['showTreeList']),
|
||||||
...mapGetters('diffs', ['isParallelView']),
|
...mapGetters('diffs', ['isParallelView']),
|
||||||
...mapGetters(['isNotesFetched', 'discussionsStructuredByLineCode']),
|
...mapGetters(['isNotesFetched', 'discussionsStructuredByLineCode']),
|
||||||
targetBranch() {
|
targetBranch() {
|
||||||
|
@ -88,6 +89,9 @@ export default {
|
||||||
canCurrentUserFork() {
|
canCurrentUserFork() {
|
||||||
return this.currentUser.canFork === true && this.currentUser.canCreateMergeRequest;
|
return this.currentUser.canFork === true && this.currentUser.canCreateMergeRequest;
|
||||||
},
|
},
|
||||||
|
showCompareVersions() {
|
||||||
|
return this.mergeRequestDiffs && this.mergeRequestDiff;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
diffViewType() {
|
diffViewType() {
|
||||||
|
@ -102,6 +106,8 @@ export default {
|
||||||
|
|
||||||
this.adjustView();
|
this.adjustView();
|
||||||
},
|
},
|
||||||
|
isLoading: 'adjustView',
|
||||||
|
showTreeList: 'adjustView',
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.setBaseConfig({ endpoint: this.endpoint, projectPath: this.projectPath });
|
this.setBaseConfig({ endpoint: this.endpoint, projectPath: this.projectPath });
|
||||||
|
@ -121,7 +127,6 @@ export default {
|
||||||
'startRenderDiffsQueue',
|
'startRenderDiffsQueue',
|
||||||
'assignDiscussionsToDiff',
|
'assignDiscussionsToDiff',
|
||||||
]),
|
]),
|
||||||
|
|
||||||
fetchData() {
|
fetchData() {
|
||||||
this.fetchDiffFiles()
|
this.fetchDiffFiles()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -152,10 +157,11 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
adjustView() {
|
adjustView() {
|
||||||
if (this.shouldShow && this.isParallelView) {
|
if (this.shouldShow) {
|
||||||
window.mrTabs.expandViewContainer();
|
this.$nextTick(() => {
|
||||||
} else {
|
window.mrTabs.resetViewContainer();
|
||||||
window.mrTabs.resetViewContainer();
|
window.mrTabs.expandViewContainer(this.showTreeList);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -168,7 +174,7 @@ export default {
|
||||||
v-if="isLoading"
|
v-if="isLoading"
|
||||||
class="loading"
|
class="loading"
|
||||||
>
|
>
|
||||||
<loading-icon />
|
<gl-loading-icon />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
|
@ -177,7 +183,7 @@ export default {
|
||||||
class="diffs tab-pane"
|
class="diffs tab-pane"
|
||||||
>
|
>
|
||||||
<compare-versions
|
<compare-versions
|
||||||
v-if="!commit && mergeRequestDiffs.length > 1"
|
v-if="showCompareVersions"
|
||||||
:merge-request-diffs="mergeRequestDiffs"
|
:merge-request-diffs="mergeRequestDiffs"
|
||||||
:merge-request-diff="mergeRequestDiff"
|
:merge-request-diff="mergeRequestDiff"
|
||||||
:start-version="startVersion"
|
:start-version="startVersion"
|
||||||
|
@ -210,22 +216,31 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<changed-files
|
<commit-widget
|
||||||
:diff-files="diffFiles"
|
v-if="commit"
|
||||||
|
:commit="commit"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div class="files d-flex prepend-top-default">
|
||||||
v-if="diffFiles.length > 0"
|
<div
|
||||||
class="files"
|
v-show="showTreeList"
|
||||||
>
|
class="diff-tree-list"
|
||||||
<diff-file
|
>
|
||||||
v-for="file in diffFiles"
|
<tree-list />
|
||||||
:key="file.newPath"
|
</div>
|
||||||
:file="file"
|
<div
|
||||||
:can-current-user-fork="canCurrentUserFork"
|
v-if="diffFiles.length > 0"
|
||||||
/>
|
class="diff-files-holder"
|
||||||
|
>
|
||||||
|
<diff-file
|
||||||
|
v-for="file in diffFiles"
|
||||||
|
:key="file.newPath"
|
||||||
|
:file="file"
|
||||||
|
:can-current-user-fork="canCurrentUserFork"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<no-changes v-else />
|
||||||
</div>
|
</div>
|
||||||
<no-changes v-else />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,171 +0,0 @@
|
||||||
<script>
|
|
||||||
import { mapGetters, mapActions } from 'vuex';
|
|
||||||
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
|
||||||
import Icon from '~/vue_shared/components/icon.vue';
|
|
||||||
import { pluralize } from '~/lib/utils/text_utility';
|
|
||||||
import { getParameterValues, mergeUrlParams } from '~/lib/utils/url_utility';
|
|
||||||
import { contentTop } from '~/lib/utils/common_utils';
|
|
||||||
import { __ } from '~/locale';
|
|
||||||
import ChangedFilesDropdown from './changed_files_dropdown.vue';
|
|
||||||
import changedFilesMixin from '../mixins/changed_files';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
Icon,
|
|
||||||
ChangedFilesDropdown,
|
|
||||||
ClipboardButton,
|
|
||||||
},
|
|
||||||
mixins: [changedFilesMixin],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isStuck: false,
|
|
||||||
maxWidth: 'auto',
|
|
||||||
offsetTop: 0,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters('diffs', ['isInlineView', 'isParallelView', 'areAllFilesCollapsed']),
|
|
||||||
sumAddedLines() {
|
|
||||||
return this.sumValues('addedLines');
|
|
||||||
},
|
|
||||||
sumRemovedLines() {
|
|
||||||
return this.sumValues('removedLines');
|
|
||||||
},
|
|
||||||
whitespaceVisible() {
|
|
||||||
return !getParameterValues('w')[0];
|
|
||||||
},
|
|
||||||
toggleWhitespaceText() {
|
|
||||||
if (this.whitespaceVisible) {
|
|
||||||
return __('Hide whitespace changes');
|
|
||||||
}
|
|
||||||
return __('Show whitespace changes');
|
|
||||||
},
|
|
||||||
toggleWhitespacePath() {
|
|
||||||
if (this.whitespaceVisible) {
|
|
||||||
return mergeUrlParams({ w: 1 }, window.location.href);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mergeUrlParams({ w: 0 }, window.location.href);
|
|
||||||
},
|
|
||||||
top() {
|
|
||||||
return `${this.offsetTop}px`;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
document.addEventListener('scroll', this.handleScroll);
|
|
||||||
this.offsetTop = contentTop();
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
document.removeEventListener('scroll', this.handleScroll);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions('diffs', ['setInlineDiffViewType', 'setParallelDiffViewType', 'expandAllFiles']),
|
|
||||||
pluralize,
|
|
||||||
handleScroll() {
|
|
||||||
if (!this.updating) {
|
|
||||||
this.$nextTick(this.updateIsStuck);
|
|
||||||
this.updating = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateIsStuck() {
|
|
||||||
if (!this.$refs.wrapper) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const scrollPosition = window.scrollY;
|
|
||||||
|
|
||||||
this.isStuck = scrollPosition + this.offsetTop >= this.$refs.placeholder.offsetTop;
|
|
||||||
this.updating = false;
|
|
||||||
},
|
|
||||||
sumValues(key) {
|
|
||||||
return this.diffFiles.reduce((total, file) => total + file[key], 0);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<span>
|
|
||||||
<div ref="placeholder"></div>
|
|
||||||
<div
|
|
||||||
ref="wrapper"
|
|
||||||
:style="{ top }"
|
|
||||||
:class="{'is-stuck': isStuck}"
|
|
||||||
class="content-block oneline-block diff-files-changed diff-files-changed-merge-request
|
|
||||||
files-changed js-diff-files-changed"
|
|
||||||
>
|
|
||||||
<div class="files-changed-inner">
|
|
||||||
<div
|
|
||||||
class="inline-parallel-buttons d-none d-md-block"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
v-if="areAllFilesCollapsed"
|
|
||||||
class="btn btn-default"
|
|
||||||
@click="expandAllFiles"
|
|
||||||
>
|
|
||||||
{{ __('Expand all') }}
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
:href="toggleWhitespacePath"
|
|
||||||
class="btn btn-default"
|
|
||||||
>
|
|
||||||
{{ toggleWhitespaceText }}
|
|
||||||
</a>
|
|
||||||
<div class="btn-group">
|
|
||||||
<button
|
|
||||||
id="inline-diff-btn"
|
|
||||||
:class="{ active: isInlineView }"
|
|
||||||
type="button"
|
|
||||||
class="btn js-inline-diff-button"
|
|
||||||
data-view-type="inline"
|
|
||||||
@click="setInlineDiffViewType"
|
|
||||||
>
|
|
||||||
{{ __('Inline') }}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
id="parallel-diff-btn"
|
|
||||||
:class="{ active: isParallelView }"
|
|
||||||
type="button"
|
|
||||||
class="btn js-parallel-diff-button"
|
|
||||||
data-view-type="parallel"
|
|
||||||
@click="setParallelDiffViewType"
|
|
||||||
>
|
|
||||||
{{ __('Side-by-side') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="commit-stat-summary dropdown">
|
|
||||||
<changed-files-dropdown
|
|
||||||
:diff-files="diffFiles"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<span
|
|
||||||
class="js-diff-stats-additions-deletions-expanded
|
|
||||||
diff-stats-additions-deletions-expanded"
|
|
||||||
>
|
|
||||||
with
|
|
||||||
<strong class="cgreen">
|
|
||||||
{{ pluralize(`${sumAddedLines} addition`, sumAddedLines) }}
|
|
||||||
</strong>
|
|
||||||
and
|
|
||||||
<strong class="cred">
|
|
||||||
{{ pluralize(`${sumRemovedLines} deletion`, sumRemovedLines) }}
|
|
||||||
</strong>
|
|
||||||
</span>
|
|
||||||
<div
|
|
||||||
class="js-diff-stats-additions-deletions-collapsed
|
|
||||||
diff-stats-additions-deletions-collapsed float-right d-sm-none"
|
|
||||||
>
|
|
||||||
<strong class="cgreen">
|
|
||||||
+{{ sumAddedLines }}
|
|
||||||
</strong>
|
|
||||||
<strong class="cred">
|
|
||||||
-{{ sumRemovedLines }}
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
|
@ -1,126 +0,0 @@
|
||||||
<script>
|
|
||||||
import Icon from '~/vue_shared/components/icon.vue';
|
|
||||||
import changedFilesMixin from '../mixins/changed_files';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
Icon,
|
|
||||||
},
|
|
||||||
mixins: [changedFilesMixin],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
searchText: '',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
filteredDiffFiles() {
|
|
||||||
return this.diffFiles.filter(file =>
|
|
||||||
file.filePath.toLowerCase().includes(this.searchText.toLowerCase()),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
clearSearch() {
|
|
||||||
this.searchText = '';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<span>
|
|
||||||
Showing
|
|
||||||
<button
|
|
||||||
class="diff-stats-summary-toggler"
|
|
||||||
data-toggle="dropdown"
|
|
||||||
type="button"
|
|
||||||
aria-expanded="false"
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
{{ n__('%d changed file', '%d changed files', diffFiles.length) }}
|
|
||||||
</span>
|
|
||||||
<icon
|
|
||||||
class="caret-icon"
|
|
||||||
name="chevron-down"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
<div class="dropdown-menu diff-file-changes">
|
|
||||||
<div class="dropdown-input">
|
|
||||||
<input
|
|
||||||
v-model="searchText"
|
|
||||||
type="search"
|
|
||||||
class="dropdown-input-field"
|
|
||||||
placeholder="Search files"
|
|
||||||
autocomplete="off"
|
|
||||||
/>
|
|
||||||
<i
|
|
||||||
v-if="searchText.length === 0"
|
|
||||||
aria-hidden="true"
|
|
||||||
data-hidden="true"
|
|
||||||
class="fa fa-search dropdown-input-search">
|
|
||||||
</i>
|
|
||||||
<i
|
|
||||||
v-else
|
|
||||||
role="button"
|
|
||||||
class="fa fa-times dropdown-input-search"
|
|
||||||
@click.stop.prevent="clearSearch"
|
|
||||||
></i>
|
|
||||||
</div>
|
|
||||||
<div class="dropdown-content">
|
|
||||||
<ul>
|
|
||||||
<li
|
|
||||||
v-for="diffFile in filteredDiffFiles"
|
|
||||||
:key="diffFile.name"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
:href="`#${diffFile.fileHash}`"
|
|
||||||
:title="diffFile.newPath"
|
|
||||||
class="diff-changed-file"
|
|
||||||
>
|
|
||||||
<icon
|
|
||||||
:name="fileChangedIcon(diffFile)"
|
|
||||||
:size="16"
|
|
||||||
:class="fileChangedClass(diffFile)"
|
|
||||||
class="diff-file-changed-icon append-right-8"
|
|
||||||
/>
|
|
||||||
<span class="diff-changed-file-content append-right-8">
|
|
||||||
<strong
|
|
||||||
v-if="diffFile.blob && diffFile.blob.name"
|
|
||||||
class="diff-changed-file-name"
|
|
||||||
>
|
|
||||||
{{ diffFile.blob.name }}
|
|
||||||
</strong>
|
|
||||||
<strong
|
|
||||||
v-else
|
|
||||||
class="diff-changed-blank-file-name"
|
|
||||||
>
|
|
||||||
{{ s__('Diffs|No file name available') }}
|
|
||||||
</strong>
|
|
||||||
<span class="diff-changed-file-path prepend-top-5">
|
|
||||||
{{ truncatedDiffPath(diffFile.blob.path) }}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span class="diff-changed-stats">
|
|
||||||
<span class="cgreen">
|
|
||||||
+{{ diffFile.addedLines }}
|
|
||||||
</span>
|
|
||||||
<span class="cred">
|
|
||||||
-{{ diffFile.removedLines }}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li
|
|
||||||
v-show="filteredDiffFiles.length === 0"
|
|
||||||
class="dropdown-menu-empty-item"
|
|
||||||
>
|
|
||||||
<a>
|
|
||||||
{{ __('No files found') }}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
129
app/assets/javascripts/diffs/components/commit_item.vue
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
<script>
|
||||||
|
import tooltip from '~/vue_shared/directives/tooltip';
|
||||||
|
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
|
||||||
|
import Icon from '~/vue_shared/components/icon.vue';
|
||||||
|
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
||||||
|
import CIIcon from '~/vue_shared/components/ci_icon.vue';
|
||||||
|
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||||
|
import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CommitItem
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------
|
||||||
|
* WARNING: Please keep changes up-to-date with the following files:
|
||||||
|
* - `views/projects/commits/_commit.html.haml`
|
||||||
|
* -----------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This Component was cloned from a HAML view. For the time being they
|
||||||
|
* coexist, but there is an issue to remove the duplication.
|
||||||
|
* https://gitlab.com/gitlab-org/gitlab-ce/issues/51613
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
directives: {
|
||||||
|
tooltip,
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
UserAvatarLink,
|
||||||
|
Icon,
|
||||||
|
ClipboardButton,
|
||||||
|
CIIcon,
|
||||||
|
TimeAgoTooltip,
|
||||||
|
CommitPipelineStatus,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
commit: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
authorName() {
|
||||||
|
return (this.commit.author && this.commit.author.name) || this.commit.authorName;
|
||||||
|
},
|
||||||
|
authorUrl() {
|
||||||
|
return (this.commit.author && this.commit.author.webUrl) || `mailto:${this.commit.authorEmail}`;
|
||||||
|
},
|
||||||
|
authorAvatar() {
|
||||||
|
return (this.commit.author && this.commit.author.avatarUrl) || this.commit.authorGravatarUrl;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<li class="commit flex-row js-toggle-container">
|
||||||
|
<user-avatar-link
|
||||||
|
:link-href="authorUrl"
|
||||||
|
:img-src="authorAvatar"
|
||||||
|
:img-alt="authorName"
|
||||||
|
:img-size="36"
|
||||||
|
class="avatar-cell d-none d-sm-block"
|
||||||
|
/>
|
||||||
|
<div class="commit-detail flex-list">
|
||||||
|
<div class="commit-content qa-commit-content">
|
||||||
|
<a
|
||||||
|
:href="commit.commitUrl"
|
||||||
|
class="commit-row-message item-title"
|
||||||
|
v-html="commit.titleHtml"
|
||||||
|
></a>
|
||||||
|
|
||||||
|
<span class="commit-row-message d-block d-sm-none">
|
||||||
|
·
|
||||||
|
{{ commit.shortId }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<button
|
||||||
|
v-if="commit.descriptionHtml"
|
||||||
|
class="text-expander js-toggle-button"
|
||||||
|
type="button"
|
||||||
|
:aria-label="__('Toggle commit description')"
|
||||||
|
>
|
||||||
|
<icon
|
||||||
|
:size="12"
|
||||||
|
name="ellipsis_h"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="commiter">
|
||||||
|
<a
|
||||||
|
:href="authorUrl"
|
||||||
|
v-text="authorName"
|
||||||
|
></a>
|
||||||
|
{{ s__('CommitWidget|authored') }}
|
||||||
|
<time-ago-tooltip
|
||||||
|
:time="commit.authoredDate"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<pre
|
||||||
|
v-if="commit.descriptionHtml"
|
||||||
|
class="commit-row-description js-toggle-content append-bottom-8"
|
||||||
|
v-html="commit.descriptionHtml"
|
||||||
|
></pre>
|
||||||
|
</div>
|
||||||
|
<div class="commit-actions flex-row d-none d-sm-flex">
|
||||||
|
<div
|
||||||
|
v-if="commit.signatureHtml"
|
||||||
|
v-html="commit.signatureHtml"
|
||||||
|
></div>
|
||||||
|
<commit-pipeline-status
|
||||||
|
v-if="commit.pipelineStatusPath"
|
||||||
|
:endpoint="commit.pipelineStatusPath"
|
||||||
|
/>
|
||||||
|
<div class="commit-sha-group">
|
||||||
|
<div
|
||||||
|
class="label label-monospace"
|
||||||
|
v-text="commit.shortId"
|
||||||
|
></div>
|
||||||
|
<clipboard-button
|
||||||
|
:text="commit.id"
|
||||||
|
:title="__('Copy commit SHA to clipboard')"
|
||||||
|
class="btn btn-default"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</template>
|
40
app/assets/javascripts/diffs/components/commit_widget.vue
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<script>
|
||||||
|
import CommitItem from './commit_item.vue';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CommitWidget
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------
|
||||||
|
* WARNING: Please keep changes up-to-date with the following files:
|
||||||
|
* - `views/projects/merge_requests/diffs/_commit_widget.html.haml`
|
||||||
|
* -----------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This Component was cloned from a HAML view. For the time being,
|
||||||
|
* they coexist, but there is an issue to remove the duplication.
|
||||||
|
* https://gitlab.com/gitlab-org/gitlab-ce/issues/51613
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CommitItem,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
commit: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="info-well prepend-top-default">
|
||||||
|
<div class="well-segment">
|
||||||
|
<ul class="blob-commit-info">
|
||||||
|
<commit-item
|
||||||
|
:commit="commit"
|
||||||
|
/>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -1,9 +1,18 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { mapActions, mapGetters, mapState } from 'vuex';
|
||||||
|
import Tooltip from '@gitlab-org/gitlab-ui/dist/directives/tooltip';
|
||||||
|
import { __ } from '~/locale';
|
||||||
|
import { getParameterValues, mergeUrlParams } from '~/lib/utils/url_utility';
|
||||||
|
import Icon from '~/vue_shared/components/icon.vue';
|
||||||
import CompareVersionsDropdown from './compare_versions_dropdown.vue';
|
import CompareVersionsDropdown from './compare_versions_dropdown.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
CompareVersionsDropdown,
|
CompareVersionsDropdown,
|
||||||
|
Icon,
|
||||||
|
},
|
||||||
|
directives: {
|
||||||
|
Tooltip,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
mergeRequestDiffs: {
|
mergeRequestDiffs: {
|
||||||
|
@ -26,30 +35,119 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapState('diffs', ['commit', 'showTreeList']),
|
||||||
|
...mapGetters('diffs', ['isInlineView', 'isParallelView', 'areAllFilesCollapsed']),
|
||||||
comparableDiffs() {
|
comparableDiffs() {
|
||||||
return this.mergeRequestDiffs.slice(1);
|
return this.mergeRequestDiffs.slice(1);
|
||||||
},
|
},
|
||||||
|
isWhitespaceVisible() {
|
||||||
|
return !getParameterValues('w')[0];
|
||||||
|
},
|
||||||
|
toggleWhitespaceText() {
|
||||||
|
if (this.isWhitespaceVisible) {
|
||||||
|
return __('Hide whitespace changes');
|
||||||
|
}
|
||||||
|
return __('Show whitespace changes');
|
||||||
|
},
|
||||||
|
toggleWhitespacePath() {
|
||||||
|
if (this.isWhitespaceVisible) {
|
||||||
|
return mergeUrlParams({ w: 1 }, window.location.href);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mergeUrlParams({ w: 0 }, window.location.href);
|
||||||
|
},
|
||||||
|
showDropdowns() {
|
||||||
|
return !this.commit && this.mergeRequestDiffs.length;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions('diffs', [
|
||||||
|
'setInlineDiffViewType',
|
||||||
|
'setParallelDiffViewType',
|
||||||
|
'expandAllFiles',
|
||||||
|
'toggleShowTreeList',
|
||||||
|
]),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="mr-version-controls">
|
<div class="mr-version-controls">
|
||||||
<div class="mr-version-menus-container content-block">
|
<div
|
||||||
Changes between
|
class="mr-version-menus-container content-block"
|
||||||
<compare-versions-dropdown
|
>
|
||||||
:other-versions="mergeRequestDiffs"
|
<button
|
||||||
:merge-request-version="mergeRequestDiff"
|
v-tooltip.hover
|
||||||
:show-commit-count="true"
|
type="button"
|
||||||
class="mr-version-dropdown"
|
class="btn btn-default append-right-8 js-toggle-tree-list"
|
||||||
/>
|
:class="{
|
||||||
and
|
active: showTreeList
|
||||||
<compare-versions-dropdown
|
}"
|
||||||
:other-versions="comparableDiffs"
|
:title="__('Toggle file browser')"
|
||||||
:start-version="startVersion"
|
@click="toggleShowTreeList"
|
||||||
:target-branch="targetBranch"
|
>
|
||||||
class="mr-version-compare-dropdown"
|
<icon
|
||||||
/>
|
name="hamburger"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
v-if="showDropdowns"
|
||||||
|
class="d-flex align-items-center compare-versions-container"
|
||||||
|
>
|
||||||
|
Changes between
|
||||||
|
<compare-versions-dropdown
|
||||||
|
:other-versions="mergeRequestDiffs"
|
||||||
|
:merge-request-version="mergeRequestDiff"
|
||||||
|
:show-commit-count="true"
|
||||||
|
class="mr-version-dropdown"
|
||||||
|
/>
|
||||||
|
and
|
||||||
|
<compare-versions-dropdown
|
||||||
|
:other-versions="comparableDiffs"
|
||||||
|
:start-version="startVersion"
|
||||||
|
:target-branch="targetBranch"
|
||||||
|
class="mr-version-compare-dropdown"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="inline-parallel-buttons d-none d-md-flex ml-auto"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
v-if="areAllFilesCollapsed"
|
||||||
|
class="btn btn-default"
|
||||||
|
@click="expandAllFiles"
|
||||||
|
>
|
||||||
|
{{ __('Expand all') }}
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
:href="toggleWhitespacePath"
|
||||||
|
class="btn btn-default"
|
||||||
|
>
|
||||||
|
{{ toggleWhitespaceText }}
|
||||||
|
</a>
|
||||||
|
<div class="btn-group prepend-left-8">
|
||||||
|
<button
|
||||||
|
id="inline-diff-btn"
|
||||||
|
:class="{ active: isInlineView }"
|
||||||
|
type="button"
|
||||||
|
class="btn js-inline-diff-button"
|
||||||
|
data-view-type="inline"
|
||||||
|
@click="setInlineDiffViewType"
|
||||||
|
>
|
||||||
|
{{ __('Inline') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
id="parallel-diff-btn"
|
||||||
|
:class="{ active: isParallelView }"
|
||||||
|
type="button"
|
||||||
|
class="btn js-parallel-diff-button"
|
||||||
|
data-view-type="parallel"
|
||||||
|
@click="setParallelDiffViewType"
|
||||||
|
>
|
||||||
|
{{ __('Side-by-side') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -108,7 +108,7 @@ export default {
|
||||||
<template>
|
<template>
|
||||||
<span class="dropdown inline">
|
<span class="dropdown inline">
|
||||||
<a
|
<a
|
||||||
class="dropdown-toggle btn btn-default"
|
class="dropdown-menu-toggle btn btn-default w-100"
|
||||||
data-toggle="dropdown"
|
data-toggle="dropdown"
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
>
|
>
|
||||||
|
@ -118,6 +118,7 @@ export default {
|
||||||
<Icon
|
<Icon
|
||||||
:size="12"
|
:size="12"
|
||||||
name="angle-down"
|
name="angle-down"
|
||||||
|
class="position-absolute"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu dropdown-select dropdown-menu-selectable">
|
<div class="dropdown-menu dropdown-select dropdown-menu-selectable">
|
||||||
|
@ -163,3 +164,10 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.dropdown {
|
||||||
|
min-width: 0;
|
||||||
|
max-height: 170px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -28,7 +28,7 @@ export default {
|
||||||
return diffModes[diffModeKey] || diffModes.replaced;
|
return diffModes[diffModeKey] || diffModes.replaced;
|
||||||
},
|
},
|
||||||
isTextFile() {
|
isTextFile() {
|
||||||
return this.diffFile.text;
|
return this.diffFile.viewer.name === 'text';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
<script>
|
<script>
|
||||||
import { mapActions, mapGetters } from 'vuex';
|
import { mapActions, mapGetters, mapState } from 'vuex';
|
||||||
import _ from 'underscore';
|
import _ from 'underscore';
|
||||||
import { __, sprintf } from '~/locale';
|
import { __, sprintf } from '~/locale';
|
||||||
import createFlash from '~/flash';
|
import createFlash from '~/flash';
|
||||||
import LoadingIcon from '~/vue_shared/components/loading_icon.vue';
|
|
||||||
import DiffFileHeader from './diff_file_header.vue';
|
import DiffFileHeader from './diff_file_header.vue';
|
||||||
import DiffContent from './diff_content.vue';
|
import DiffContent from './diff_content.vue';
|
||||||
|
|
||||||
|
@ -11,7 +10,6 @@ export default {
|
||||||
components: {
|
components: {
|
||||||
DiffFileHeader,
|
DiffFileHeader,
|
||||||
DiffContent,
|
DiffContent,
|
||||||
LoadingIcon,
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
file: {
|
file: {
|
||||||
|
@ -30,6 +28,7 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapState('diffs', ['currentDiffFileId']),
|
||||||
...mapGetters(['isNotesFetched', 'discussionsStructuredByLineCode']),
|
...mapGetters(['isNotesFetched', 'discussionsStructuredByLineCode']),
|
||||||
isCollapsed() {
|
isCollapsed() {
|
||||||
return this.file.collapsed || false;
|
return this.file.collapsed || false;
|
||||||
|
@ -103,6 +102,9 @@ export default {
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
:id="file.fileHash"
|
:id="file.fileHash"
|
||||||
|
:class="{
|
||||||
|
'is-active': currentDiffFileId === file.fileHash
|
||||||
|
}"
|
||||||
class="diff-file file-holder"
|
class="diff-file file-holder"
|
||||||
>
|
>
|
||||||
<diff-file-header
|
<diff-file-header
|
||||||
|
@ -144,7 +146,7 @@ export default {
|
||||||
:class="{ hidden: isCollapsed || file.tooLarge }"
|
:class="{ hidden: isCollapsed || file.tooLarge }"
|
||||||
:diff-file="file"
|
:diff-file="file"
|
||||||
/>
|
/>
|
||||||
<loading-icon
|
<gl-loading-icon
|
||||||
v-if="showLoadingIcon"
|
v-if="showLoadingIcon"
|
||||||
class="diff-content loading"
|
class="diff-content loading"
|
||||||
/>
|
/>
|
||||||
|
@ -170,3 +172,20 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@keyframes shadow-fade {
|
||||||
|
from {
|
||||||
|
box-shadow: 0 0 4px #919191;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
box-shadow: 0 0 0 #dfdfdf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.diff-file.is-active {
|
||||||
|
box-shadow: 0 0 0 #dfdfdf;
|
||||||
|
animation: shadow-fade 1.2s 0.1s 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -166,23 +166,21 @@ export default {
|
||||||
:title="diffFile.oldPath"
|
:title="diffFile.oldPath"
|
||||||
class="file-title-name"
|
class="file-title-name"
|
||||||
data-container="body"
|
data-container="body"
|
||||||
>
|
v-html="diffFile.oldPathHtml"
|
||||||
{{ diffFile.oldPath }}
|
></strong>
|
||||||
</strong>
|
|
||||||
→
|
→
|
||||||
<strong
|
<strong
|
||||||
v-tooltip
|
v-tooltip
|
||||||
:title="diffFile.newPath"
|
:title="diffFile.newPath"
|
||||||
class="file-title-name"
|
class="file-title-name"
|
||||||
data-container="body"
|
data-container="body"
|
||||||
>
|
v-html="diffFile.newPathHtml"
|
||||||
{{ diffFile.newPath }}
|
></strong>
|
||||||
</strong>
|
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<strong
|
<strong
|
||||||
v-tooltip
|
|
||||||
v-else
|
v-else
|
||||||
|
v-tooltip
|
||||||
:title="filePath"
|
:title="filePath"
|
||||||
class="file-title-name"
|
class="file-title-name"
|
||||||
data-container="body"
|
data-container="body"
|
||||||
|
@ -255,8 +253,8 @@ export default {
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
v-tooltip
|
|
||||||
v-if="diffFile.externalUrl"
|
v-if="diffFile.externalUrl"
|
||||||
|
v-tooltip
|
||||||
:href="diffFile.externalUrl"
|
:href="diffFile.externalUrl"
|
||||||
:title="`View on ${diffFile.formattedExternalUrl}`"
|
:title="`View on ${diffFile.formattedExternalUrl}`"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
import { mapActions } from 'vuex';
|
import { mapActions } from 'vuex';
|
||||||
import Icon from '~/vue_shared/components/icon.vue';
|
import Icon from '~/vue_shared/components/icon.vue';
|
||||||
import tooltip from '~/vue_shared/directives/tooltip';
|
|
||||||
import { pluralize, truncate } from '~/lib/utils/text_utility';
|
import { pluralize, truncate } from '~/lib/utils/text_utility';
|
||||||
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
|
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||||
import { COUNT_OF_AVATARS_IN_GUTTER, LENGTH_OF_AVATAR_TOOLTIP } from '../constants';
|
import { COUNT_OF_AVATARS_IN_GUTTER, LENGTH_OF_AVATAR_TOOLTIP } from '../constants';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
directives: {
|
|
||||||
tooltip,
|
|
||||||
},
|
|
||||||
components: {
|
components: {
|
||||||
Icon,
|
Icon,
|
||||||
UserAvatarImage,
|
UserAvatarImage,
|
||||||
|
@ -91,10 +87,10 @@ export default {
|
||||||
@click.native="toggleDiscussions"
|
@click.native="toggleDiscussions"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
v-tooltip
|
|
||||||
v-if="moreText"
|
v-if="moreText"
|
||||||
|
v-gl-tooltip
|
||||||
:title="moreText"
|
:title="moreText"
|
||||||
class="diff-comments-more-count has-tooltip js-diff-comment-avatar js-diff-comment-plus"
|
class="diff-comments-more-count js-diff-comment-avatar js-diff-comment-plus"
|
||||||
data-container="body"
|
data-container="body"
|
||||||
data-placement="top"
|
data-placement="top"
|
||||||
role="button"
|
role="button"
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
<script>
|
<script>
|
||||||
import { mapState, mapGetters, mapActions } from 'vuex';
|
import { mapState, mapGetters, mapActions } from 'vuex';
|
||||||
import createFlash from '~/flash';
|
|
||||||
import { s__ } from '~/locale';
|
import { s__ } from '~/locale';
|
||||||
import noteForm from '../../notes/components/note_form.vue';
|
import noteForm from '../../notes/components/note_form.vue';
|
||||||
import { getNoteFormData } from '../store/utils';
|
|
||||||
import autosave from '../../notes/mixins/autosave';
|
import autosave from '../../notes/mixins/autosave';
|
||||||
import { DIFF_NOTE_TYPE } from '../constants';
|
import { DIFF_NOTE_TYPE } from '../constants';
|
||||||
import { reduceDiscussionsToLineCodes } from '../../notes/stores/utils';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
@ -22,7 +19,7 @@ export default {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
position: {
|
linePosition: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
default: '',
|
default: '',
|
||||||
|
@ -39,6 +36,16 @@ export default {
|
||||||
}),
|
}),
|
||||||
...mapGetters('diffs', ['getDiffFileByHash']),
|
...mapGetters('diffs', ['getDiffFileByHash']),
|
||||||
...mapGetters(['isLoggedIn', 'noteableType', 'getNoteableData', 'getNotesDataByProp']),
|
...mapGetters(['isLoggedIn', 'noteableType', 'getNoteableData', 'getNotesDataByProp']),
|
||||||
|
formData() {
|
||||||
|
return {
|
||||||
|
noteableData: this.noteableData,
|
||||||
|
noteableType: this.noteableType,
|
||||||
|
noteTargetLine: this.noteTargetLine,
|
||||||
|
diffViewType: this.diffViewType,
|
||||||
|
diffFile: this.getDiffFileByHash(this.diffFileHash),
|
||||||
|
linePosition: this.linePosition,
|
||||||
|
};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.isLoggedIn) {
|
if (this.isLoggedIn) {
|
||||||
|
@ -53,8 +60,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions('diffs', ['cancelCommentForm', 'assignDiscussionsToDiff']),
|
...mapActions('diffs', ['cancelCommentForm', 'assignDiscussionsToDiff', 'saveDiffDiscussion']),
|
||||||
...mapActions(['saveNote', 'refetchDiscussionById']),
|
|
||||||
handleCancelCommentForm(shouldConfirm, isDirty) {
|
handleCancelCommentForm(shouldConfirm, isDirty) {
|
||||||
if (shouldConfirm && isDirty) {
|
if (shouldConfirm && isDirty) {
|
||||||
const msg = s__('Notes|Are you sure you want to cancel creating this comment?');
|
const msg = s__('Notes|Are you sure you want to cancel creating this comment?');
|
||||||
|
@ -73,35 +79,9 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleSaveNote(note) {
|
handleSaveNote(note) {
|
||||||
const selectedDiffFile = this.getDiffFileByHash(this.diffFileHash);
|
return this.saveDiffDiscussion({ note, formData: this.formData }).then(() =>
|
||||||
const postData = getNoteFormData({
|
this.handleCancelCommentForm(),
|
||||||
note,
|
);
|
||||||
noteableData: this.noteableData,
|
|
||||||
noteableType: this.noteableType,
|
|
||||||
noteTargetLine: this.noteTargetLine,
|
|
||||||
diffViewType: this.diffViewType,
|
|
||||||
diffFile: selectedDiffFile,
|
|
||||||
linePosition: this.position,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.saveNote(postData)
|
|
||||||
.then(result => {
|
|
||||||
const endpoint = this.getNotesDataByProp('discussionsPath');
|
|
||||||
|
|
||||||
this.refetchDiscussionById({ path: endpoint, discussionId: result.discussion_id })
|
|
||||||
.then(selectedDiscussion => {
|
|
||||||
const lineCodeDiscussions = reduceDiscussionsToLineCodes([selectedDiscussion]);
|
|
||||||
this.assignDiscussionsToDiff(lineCodeDiscussions);
|
|
||||||
|
|
||||||
this.handleCancelCommentForm();
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
createFlash(s__('MergeRequests|Updating discussions failed'));
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
createFlash(s__('MergeRequests|Saving the comment failed'));
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
30
app/assets/javascripts/diffs/components/file_row_stats.vue
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
file: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<span
|
||||||
|
v-once
|
||||||
|
class="file-row-stats"
|
||||||
|
>
|
||||||
|
<span class="cgreen">
|
||||||
|
+{{ file.addedLines }}
|
||||||
|
</span>
|
||||||
|
<span class="cred">
|
||||||
|
-{{ file.removedLines }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.file-row-stats {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -43,18 +43,18 @@ export default {
|
||||||
v-for="(line, index) in diffLines"
|
v-for="(line, index) in diffLines"
|
||||||
>
|
>
|
||||||
<inline-diff-table-row
|
<inline-diff-table-row
|
||||||
|
:key="line.lineCode"
|
||||||
:file-hash="diffFile.fileHash"
|
:file-hash="diffFile.fileHash"
|
||||||
:context-lines-path="diffFile.contextLinesPath"
|
:context-lines-path="diffFile.contextLinesPath"
|
||||||
:line="line"
|
:line="line"
|
||||||
:is-bottom="index + 1 === diffLinesLength"
|
:is-bottom="index + 1 === diffLinesLength"
|
||||||
:key="line.lineCode"
|
|
||||||
/>
|
/>
|
||||||
<inline-diff-comment-row
|
<inline-diff-comment-row
|
||||||
v-if="shouldRenderInlineCommentRow(line)"
|
v-if="shouldRenderInlineCommentRow(line)"
|
||||||
|
:key="index"
|
||||||
:diff-file-hash="diffFile.fileHash"
|
:diff-file-hash="diffFile.fileHash"
|
||||||
:line="line"
|
:line="line"
|
||||||
:line-index="index"
|
:line-index="index"
|
||||||
:key="index"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -38,7 +38,7 @@ export default {
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<a
|
<a
|
||||||
:href="newBlobPath"
|
:href="newBlobPath"
|
||||||
class="btn btn-save"
|
class="btn btn-success"
|
||||||
>
|
>
|
||||||
{{ __('Create commit') }}
|
{{ __('Create commit') }}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -92,7 +92,7 @@ export default {
|
||||||
:diff-file-hash="diffFileHash"
|
:diff-file-hash="diffFileHash"
|
||||||
:line="line.left"
|
:line="line.left"
|
||||||
:note-target-line="line.left"
|
:note-target-line="line.left"
|
||||||
position="left"
|
line-position="left"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td class="notes_line new"></td>
|
<td class="notes_line new"></td>
|
||||||
|
@ -111,7 +111,7 @@ export default {
|
||||||
:diff-file-hash="diffFileHash"
|
:diff-file-hash="diffFileHash"
|
||||||
:line="line.right"
|
:line="line.right"
|
||||||
:note-target-line="line.right"
|
:note-target-line="line.right"
|
||||||
position="right"
|
line-position="right"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -45,11 +45,11 @@ export default {
|
||||||
v-for="(line, index) in diffLines"
|
v-for="(line, index) in diffLines"
|
||||||
>
|
>
|
||||||
<parallel-diff-table-row
|
<parallel-diff-table-row
|
||||||
|
:key="index"
|
||||||
:file-hash="diffFile.fileHash"
|
:file-hash="diffFile.fileHash"
|
||||||
:context-lines-path="diffFile.contextLinesPath"
|
:context-lines-path="diffFile.contextLinesPath"
|
||||||
:line="line"
|
:line="line"
|
||||||
:is-bottom="index + 1 === diffLinesLength"
|
:is-bottom="index + 1 === diffLinesLength"
|
||||||
:key="index"
|
|
||||||
/>
|
/>
|
||||||
<parallel-diff-comment-row
|
<parallel-diff-comment-row
|
||||||
v-if="shouldRenderParallelCommentRow(line)"
|
v-if="shouldRenderParallelCommentRow(line)"
|
||||||
|
|
101
app/assets/javascripts/diffs/components/tree_list.vue
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
<script>
|
||||||
|
import { mapActions, mapGetters, mapState } from 'vuex';
|
||||||
|
import Icon from '~/vue_shared/components/icon.vue';
|
||||||
|
import FileRow from '~/vue_shared/components/file_row.vue';
|
||||||
|
import FileRowStats from './file_row_stats.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Icon,
|
||||||
|
FileRow,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
search: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState('diffs', ['tree', 'addedLines', 'removedLines']),
|
||||||
|
...mapGetters('diffs', ['allBlobs', 'diffFilesLength']),
|
||||||
|
filteredTreeList() {
|
||||||
|
const search = this.search.toLowerCase().trim();
|
||||||
|
|
||||||
|
if (search === '') return this.tree;
|
||||||
|
|
||||||
|
return this.allBlobs.filter(f => f.name.toLowerCase().indexOf(search) >= 0);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions('diffs', ['toggleTreeOpen', 'scrollToFile']),
|
||||||
|
clearSearch() {
|
||||||
|
this.search = '';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
FileRowStats,
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="tree-list-holder d-flex flex-column">
|
||||||
|
<div class="append-bottom-8 position-relative tree-list-search">
|
||||||
|
<icon
|
||||||
|
name="search"
|
||||||
|
class="position-absolute tree-list-icon"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model="search"
|
||||||
|
:placeholder="s__('MergeRequest|Filter files')"
|
||||||
|
type="search"
|
||||||
|
class="form-control"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
v-show="search"
|
||||||
|
:aria-label="__('Clear search')"
|
||||||
|
type="button"
|
||||||
|
class="position-absolute tree-list-icon tree-list-clear-icon border-0 p-0"
|
||||||
|
@click="clearSearch"
|
||||||
|
>
|
||||||
|
<icon
|
||||||
|
name="close"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="tree-list-scroll"
|
||||||
|
>
|
||||||
|
<template v-if="filteredTreeList.length">
|
||||||
|
<file-row
|
||||||
|
v-for="file in filteredTreeList"
|
||||||
|
:key="file.key"
|
||||||
|
:file="file"
|
||||||
|
:level="0"
|
||||||
|
:hide-extra-on-tree="true"
|
||||||
|
:extra-component="$options.FileRowStats"
|
||||||
|
:show-changed-icon="true"
|
||||||
|
@toggleTreeOpen="toggleTreeOpen"
|
||||||
|
@clickFile="scrollToFile"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<p
|
||||||
|
v-else
|
||||||
|
class="prepend-top-20 append-bottom-20 text-center"
|
||||||
|
>
|
||||||
|
{{ s__('MergeRequest|No files found') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-once
|
||||||
|
class="pt-3 pb-3 text-center"
|
||||||
|
>
|
||||||
|
{{ n__('%d changed file', '%d changed files', diffFilesLength) }}
|
||||||
|
<div>
|
||||||
|
<span class="cgreen">
|
||||||
|
{{ n__('%d addition', '%d additions', addedLines) }}
|
||||||
|
</span>
|
||||||
|
<span class="cred">
|
||||||
|
{{ n__('%d deleted', '%d deletions', removedLines) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -7,6 +7,7 @@ export const CONTEXT_LINE_TYPE = 'context';
|
||||||
export const EMPTY_CELL_TYPE = 'empty-cell';
|
export const EMPTY_CELL_TYPE = 'empty-cell';
|
||||||
export const COMMENT_FORM_TYPE = 'commentForm';
|
export const COMMENT_FORM_TYPE = 'commentForm';
|
||||||
export const DIFF_NOTE_TYPE = 'DiffNote';
|
export const DIFF_NOTE_TYPE = 'DiffNote';
|
||||||
|
export const LEGACY_DIFF_NOTE_TYPE = 'LegacyDiffNote';
|
||||||
export const NOTE_TYPE = 'Note';
|
export const NOTE_TYPE = 'Note';
|
||||||
export const NEW_LINE_TYPE = 'new';
|
export const NEW_LINE_TYPE = 'new';
|
||||||
export const OLD_LINE_TYPE = 'old';
|
export const OLD_LINE_TYPE = 'old';
|
||||||
|
@ -28,3 +29,5 @@ export const LENGTH_OF_AVATAR_TOOLTIP = 17;
|
||||||
|
|
||||||
export const LINES_TO_BE_RENDERED_DIRECTLY = 100;
|
export const LINES_TO_BE_RENDERED_DIRECTLY = 100;
|
||||||
export const MAX_LINES_TO_BE_RENDERED = 2000;
|
export const MAX_LINES_TO_BE_RENDERED = 2000;
|
||||||
|
|
||||||
|
export const MR_TREE_SHOW_KEY = 'mr_tree_show';
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
diffFiles: {
|
|
||||||
type: Array,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
fileChangedIcon(diffFile) {
|
|
||||||
if (diffFile.deletedFile) {
|
|
||||||
return 'file-deletion';
|
|
||||||
} else if (diffFile.newFile) {
|
|
||||||
return 'file-addition';
|
|
||||||
}
|
|
||||||
return 'file-modified';
|
|
||||||
},
|
|
||||||
fileChangedClass(diffFile) {
|
|
||||||
if (diffFile.deletedFile) {
|
|
||||||
return 'cred';
|
|
||||||
} else if (diffFile.newFile) {
|
|
||||||
return 'cgreen';
|
|
||||||
}
|
|
||||||
|
|
||||||
return '';
|
|
||||||
},
|
|
||||||
truncatedDiffPath(path) {
|
|
||||||
const maxLength = 60;
|
|
||||||
|
|
||||||
if (path.length > maxLength) {
|
|
||||||
const start = path.length - maxLength;
|
|
||||||
const end = start + maxLength;
|
|
||||||
return `...${path.slice(start, end)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return path;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -1,14 +1,18 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import axios from '~/lib/utils/axios_utils';
|
import axios from '~/lib/utils/axios_utils';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
|
import createFlash from '~/flash';
|
||||||
|
import { s__ } from '~/locale';
|
||||||
import { handleLocationHash, historyPushState } from '~/lib/utils/common_utils';
|
import { handleLocationHash, historyPushState } from '~/lib/utils/common_utils';
|
||||||
import { mergeUrlParams, getLocationHash } from '~/lib/utils/url_utility';
|
import { mergeUrlParams, getLocationHash } from '~/lib/utils/url_utility';
|
||||||
import { getDiffPositionByLineCode } from './utils';
|
import { reduceDiscussionsToLineCodes } from '../../notes/stores/utils';
|
||||||
|
import { getDiffPositionByLineCode, getNoteFormData } from './utils';
|
||||||
import * as types from './mutation_types';
|
import * as types from './mutation_types';
|
||||||
import {
|
import {
|
||||||
PARALLEL_DIFF_VIEW_TYPE,
|
PARALLEL_DIFF_VIEW_TYPE,
|
||||||
INLINE_DIFF_VIEW_TYPE,
|
INLINE_DIFF_VIEW_TYPE,
|
||||||
DIFF_VIEW_COOKIE_NAME,
|
DIFF_VIEW_COOKIE_NAME,
|
||||||
|
MR_TREE_SHOW_KEY,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
|
|
||||||
export const setBaseConfig = ({ commit }, options) => {
|
export const setBaseConfig = ({ commit }, options) => {
|
||||||
|
@ -178,5 +182,37 @@ export const toggleFileDiscussions = ({ getters, dispatch }, diff) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const saveDiffDiscussion = ({ dispatch }, { note, formData }) => {
|
||||||
|
const postData = getNoteFormData({
|
||||||
|
note,
|
||||||
|
...formData,
|
||||||
|
});
|
||||||
|
|
||||||
|
return dispatch('saveNote', postData, { root: true })
|
||||||
|
.then(result => dispatch('updateDiscussion', result.discussion, { root: true }))
|
||||||
|
.then(discussion =>
|
||||||
|
dispatch('assignDiscussionsToDiff', reduceDiscussionsToLineCodes([discussion])),
|
||||||
|
)
|
||||||
|
.catch(() => createFlash(s__('MergeRequests|Saving the comment failed')));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const toggleTreeOpen = ({ commit }, path) => {
|
||||||
|
commit(types.TOGGLE_FOLDER_OPEN, path);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const scrollToFile = ({ state, commit }, path) => {
|
||||||
|
const { fileHash } = state.treeEntries[path];
|
||||||
|
document.location.hash = fileHash;
|
||||||
|
|
||||||
|
commit(types.UPDATE_CURRENT_DIFF_FILE_ID, fileHash);
|
||||||
|
|
||||||
|
setTimeout(() => commit(types.UPDATE_CURRENT_DIFF_FILE_ID, ''), 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const toggleShowTreeList = ({ commit, state }) => {
|
||||||
|
commit(types.TOGGLE_SHOW_TREE_LIST);
|
||||||
|
localStorage.setItem(MR_TREE_SHOW_KEY, state.showTreeList);
|
||||||
|
};
|
||||||
|
|
||||||
// prevent babel-plugin-rewire from generating an invalid default during karma tests
|
// prevent babel-plugin-rewire from generating an invalid default during karma tests
|
||||||
export default () => {};
|
export default () => {};
|
||||||
|
|
|
@ -110,5 +110,9 @@ export const shouldRenderInlineCommentRow = state => line => {
|
||||||
export const getDiffFileByHash = state => fileHash =>
|
export const getDiffFileByHash = state => fileHash =>
|
||||||
state.diffFiles.find(file => file.fileHash === fileHash);
|
state.diffFiles.find(file => file.fileHash === fileHash);
|
||||||
|
|
||||||
|
export const allBlobs = state => Object.values(state.treeEntries).filter(f => f.type === 'blob');
|
||||||
|
|
||||||
|
export const diffFilesLength = state => state.diffFiles.length;
|
||||||
|
|
||||||
// prevent babel-plugin-rewire from generating an invalid default during karma tests
|
// prevent babel-plugin-rewire from generating an invalid default during karma tests
|
||||||
export default () => {};
|
export default () => {};
|
||||||
|
|