New upstream version 13.4.6

This commit is contained in:
Pirate Praveen 2020-11-24 15:15:51 +05:30
parent 01760414a6
commit a557ad5f5f
5420 changed files with 256471 additions and 96876 deletions

View file

@ -14,5 +14,5 @@ indent_size = 2
indent_style = space indent_style = space
charset = utf-8 charset = utf-8
[*.{md,markdown}] [*.{md,markdown,js.snap}]
trim_trailing_whitespace = false trim_trailing_whitespace = false

View file

@ -17,6 +17,7 @@ settings:
config: './config/webpack.config.js' config: './config/webpack.config.js'
rules: rules:
import/no-commonjs: error import/no-commonjs: error
import/no-default-export: off
no-underscore-dangle: no-underscore-dangle:
- error - error
- allow: - allow:
@ -35,7 +36,7 @@ rules:
# Disabled for now, to make the plugin-vue 4.5 -> 5.0 update smoother # Disabled for now, to make the plugin-vue 4.5 -> 5.0 update smoother
vue/no-confusing-v-for-v-if: error vue/no-confusing-v-for-v-if: error
vue/no-use-v-if-with-v-for: off vue/no-use-v-if-with-v-for: off
vue/no-v-html: off vue/no-v-html: error
vue/use-v-on-exact: off vue/use-v-on-exact: off
# all offenses of no-jquery/no-animate-toggle are false positives ( $toast.show() ) # all offenses of no-jquery/no-animate-toggle are false positives ( $toast.show() )
no-jquery/no-animate-toggle: off no-jquery/no-animate-toggle: off

510
.gitignore vendored
View file

@ -71,6 +71,7 @@ eslint-report.html
/builds* /builds*
/.gitlab_workhorse_secret /.gitlab_workhorse_secret
/.gitlab_pages_secret /.gitlab_pages_secret
/.gitlab_kas_secret
/webpack-report/ /webpack-report/
/knapsack/ /knapsack/
/rspec_flaky/ /rspec_flaky/
@ -93,513 +94,6 @@ webpack-dev-server.json
.solargraph.yml .solargraph.yml
apollo.config.js apollo.config.js
/tmp/matching_foss_tests.txt /tmp/matching_foss_tests.txt
/tmp/matching_tests.txt
ee/changelogs/unreleased-ee ee/changelogs/unreleased-ee
# Likely anything 2017 was removed in bac4d96dcfc, 381b706559b, or cfae6ec2647
db/schema_migrations/2014*
db/schema_migrations/2015*
db/schema_migrations/2016*
db/schema_migrations/2017*
# Removed in 02ea9bc792b9236ea8854154ea5caef1a03b07b4
db/schema_migrations/20171230123729
db/schema_migrations/20180101160629
db/schema_migrations/20180101160630
db/schema_migrations/20180102220145
db/schema_migrations/20180103123548
db/schema_migrations/20180104131052
db/schema_migrations/20180105212544
db/schema_migrations/20180109183319
db/schema_migrations/20180113220114
db/schema_migrations/20180115094742
db/schema_migrations/20180115113902
db/schema_migrations/20180115201419
db/schema_migrations/20180116193854
db/schema_migrations/20180119121225
db/schema_migrations/20180119135717
db/schema_migrations/20180119160751
db/schema_migrations/20180122154930
db/schema_migrations/20180122162010
db/schema_migrations/20180125214301
db/schema_migrations/20180129193323
db/schema_migrations/20180201102129
db/schema_migrations/20180201110056
db/schema_migrations/20180201145907
db/schema_migrations/20180204200836
db/schema_migrations/20180206200543
db/schema_migrations/20180208183958
db/schema_migrations/20180209115333
db/schema_migrations/20180209165249
db/schema_migrations/20180212030105
db/schema_migrations/20180212101828
db/schema_migrations/20180212101928
db/schema_migrations/20180212102028
db/schema_migrations/20180213131630
db/schema_migrations/20180214093516
db/schema_migrations/20180214155405
db/schema_migrations/20180215181245
db/schema_migrations/20180216120000
db/schema_migrations/20180216120010
db/schema_migrations/20180216120020
db/schema_migrations/20180216120030
db/schema_migrations/20180216120040
db/schema_migrations/20180216120050
db/schema_migrations/20180216121020
db/schema_migrations/20180216121030
db/schema_migrations/20180219153455
db/schema_migrations/20180220150310
db/schema_migrations/20180221151752
db/schema_migrations/20180222043024
db/schema_migrations/20180223120443
db/schema_migrations/20180223124427
db/schema_migrations/20180223144945
db/schema_migrations/20180226050030
db/schema_migrations/20180227182112
db/schema_migrations/20180228172924
db/schema_migrations/20180301010859
db/schema_migrations/20180301084653
db/schema_migrations/20180302152117
db/schema_migrations/20180305095250
db/schema_migrations/20180305100050
db/schema_migrations/20180305144721
db/schema_migrations/20180306074045
db/schema_migrations/20180306134842
db/schema_migrations/20180306164012
db/schema_migrations/20180307012445
db/schema_migrations/20180308052825
db/schema_migrations/20180308125206
db/schema_migrations/20180309121820
db/schema_migrations/20180309160427
db/schema_migrations/20180314100728
db/schema_migrations/20180314145917
db/schema_migrations/20180315160435
db/schema_migrations/20180319190020
db/schema_migrations/20180320182229
db/schema_migrations/20180323150945
db/schema_migrations/20180326202229
db/schema_migrations/20180327101207
db/schema_migrations/20180330121048
db/schema_migrations/20180403035759
db/schema_migrations/20180405101928
db/schema_migrations/20180405142733
db/schema_migrations/20180408143354
db/schema_migrations/20180408143355
db/schema_migrations/20180409170809
db/schema_migrations/20180413022611
db/schema_migrations/20180416155103
db/schema_migrations/20180417090132
db/schema_migrations/20180417101040
db/schema_migrations/20180417101940
db/schema_migrations/20180418053107
db/schema_migrations/20180420010016
db/schema_migrations/20180420010616
db/schema_migrations/20180420080616
db/schema_migrations/20180423204600
db/schema_migrations/20180424090541
db/schema_migrations/20180424134533
db/schema_migrations/20180424151928
db/schema_migrations/20180424160449
db/schema_migrations/20180425075446
db/schema_migrations/20180425131009
db/schema_migrations/20180425205249
db/schema_migrations/20180426102016
db/schema_migrations/20180430101916
db/schema_migrations/20180430143705
db/schema_migrations/20180502122856
db/schema_migrations/20180503131624
db/schema_migrations/20180503141722
db/schema_migrations/20180503150427
db/schema_migrations/20180503175053
db/schema_migrations/20180503175054
db/schema_migrations/20180503193542
db/schema_migrations/20180503193953
db/schema_migrations/20180503200320
db/schema_migrations/20180504195842
db/schema_migrations/20180507083701
db/schema_migrations/20180508055821
db/schema_migrations/20180508100222
db/schema_migrations/20180508102840
db/schema_migrations/20180508135515
db/schema_migrations/20180511090724
db/schema_migrations/20180511131058
db/schema_migrations/20180511174224
db/schema_migrations/20180512061621
db/schema_migrations/20180514161336
db/schema_migrations/20180515005612
db/schema_migrations/20180515121227
db/schema_migrations/20180517082340
db/schema_migrations/20180523042841
db/schema_migrations/20180523125103
db/schema_migrations/20180524132016
db/schema_migrations/20180529093006
db/schema_migrations/20180529152628
db/schema_migrations/20180530135500
db/schema_migrations/20180531185349
db/schema_migrations/20180531220618
db/schema_migrations/20180601213245
db/schema_migrations/20180603190921
db/schema_migrations/20180604123514
db/schema_migrations/20180607071808
db/schema_migrations/20180608091413
db/schema_migrations/20180608110058
db/schema_migrations/20180608201435
db/schema_migrations/20180612103626
db/schema_migrations/20180613081317
db/schema_migrations/20180625113853
db/schema_migrations/20180626125654
db/schema_migrations/20180628124813
db/schema_migrations/20180629153018
db/schema_migrations/20180629191052
db/schema_migrations/20180702120647
db/schema_migrations/20180702124358
db/schema_migrations/20180702134423
db/schema_migrations/20180704145007
db/schema_migrations/20180704204006
db/schema_migrations/20180705160945
db/schema_migrations/20180706223200
db/schema_migrations/20180710162338
db/schema_migrations/20180711103851
db/schema_migrations/20180711103922
db/schema_migrations/20180713092803
db/schema_migrations/20180717125853
db/schema_migrations/20180718005113
db/schema_migrations/20180720023512
db/schema_migrations/20180722103201
db/schema_migrations/20180723135214
db/schema_migrations/20180726172057
db/schema_migrations/20180807153545
db/schema_migrations/20180808162000
db/schema_migrations/20180809195358
db/schema_migrations/20180813101999
db/schema_migrations/20180813102000
db/schema_migrations/20180814153625
db/schema_migrations/20180815040323
db/schema_migrations/20180815160409
db/schema_migrations/20180815170510
db/schema_migrations/20180815175440
db/schema_migrations/20180816161409
db/schema_migrations/20180816193530
db/schema_migrations/20180824202952
db/schema_migrations/20180826111825
db/schema_migrations/20180831164905
db/schema_migrations/20180831164907
db/schema_migrations/20180831164908
db/schema_migrations/20180831164909
db/schema_migrations/20180831164910
db/schema_migrations/20180901171833
db/schema_migrations/20180901200537
db/schema_migrations/20180902070406
db/schema_migrations/20180906101639
db/schema_migrations/20180907015926
db/schema_migrations/20180910115836
db/schema_migrations/20180910153412
db/schema_migrations/20180910153413
db/schema_migrations/20180912111628
db/schema_migrations/20180913142237
db/schema_migrations/20180914162043
db/schema_migrations/20180914201132
db/schema_migrations/20180916011959
db/schema_migrations/20180917172041
db/schema_migrations/20180924141949
db/schema_migrations/20180924190739
db/schema_migrations/20180924201039
db/schema_migrations/20180925200829
db/schema_migrations/20180927073410
db/schema_migrations/20181002172433
db/schema_migrations/20181005110927
db/schema_migrations/20181005125926
db/schema_migrations/20181006004100
db/schema_migrations/20181008145341
db/schema_migrations/20181008145359
db/schema_migrations/20181008200441
db/schema_migrations/20181009190428
db/schema_migrations/20181010133639
db/schema_migrations/20181010235606
db/schema_migrations/20181013005024
db/schema_migrations/20181014203236
db/schema_migrations/20181015155839
db/schema_migrations/20181016141739
db/schema_migrations/20181016152238
db/schema_migrations/20181017001059
db/schema_migrations/20181019032400
db/schema_migrations/20181019032408
db/schema_migrations/20181019105553
db/schema_migrations/20181022135539
db/schema_migrations/20181022173835
db/schema_migrations/20181023104858
db/schema_migrations/20181023144439
db/schema_migrations/20181025115728
db/schema_migrations/20181026091631
db/schema_migrations/20181026143227
db/schema_migrations/20181027114222
db/schema_migrations/20181028120717
db/schema_migrations/20181030135124
db/schema_migrations/20181030154446
db/schema_migrations/20181031145139
db/schema_migrations/20181031190558
db/schema_migrations/20181031190559
db/schema_migrations/20181101091005
db/schema_migrations/20181101091124
db/schema_migrations/20181101144347
db/schema_migrations/20181101191341
db/schema_migrations/20181105201455
db/schema_migrations/20181106135939
db/schema_migrations/20181107054254
db/schema_migrations/20181108091549
db/schema_migrations/20181112103239
db/schema_migrations/20181115140140
db/schema_migrations/20181116050532
db/schema_migrations/20181116141415
db/schema_migrations/20181116141504
db/schema_migrations/20181119081539
db/schema_migrations/20181119132520
db/schema_migrations/20181120082911
db/schema_migrations/20181120091639
db/schema_migrations/20181120151656
db/schema_migrations/20181121101842
db/schema_migrations/20181121101843
db/schema_migrations/20181121111200
db/schema_migrations/20181122160027
db/schema_migrations/20181123042307
db/schema_migrations/20181123135036
db/schema_migrations/20181123144235
db/schema_migrations/20181126150622
db/schema_migrations/20181126153547
db/schema_migrations/20181128123704
db/schema_migrations/20181129104854
db/schema_migrations/20181129104944
db/schema_migrations/20181130102132
db/schema_migrations/20181203002526
db/schema_migrations/20181205171941
db/schema_migrations/20181211092510
db/schema_migrations/20181211092514
db/schema_migrations/20181212104941
db/schema_migrations/20181212171634
db/schema_migrations/20181219130552
db/schema_migrations/20181219145520
db/schema_migrations/20181219145521
# Removed in 71a3b0e470c64fccbb902390b1f856ee1547a978
db/schema_migrations/20190225160300
# Removed in 44f9d16edca328e5bb234b853f0d670ee0b30a26
db/schema_migrations/20200615101135
# Removed in cfae6ec2647
db/schema_migrations/20180502134117
db/schema_migrations/20180521162137
db/schema_migrations/20180619121030
db/schema_migrations/20180723130817
db/schema_migrations/20180906051323
db/schema_migrations/20180913051323
db/schema_migrations/20180916014356
db/schema_migrations/20181014121030
db/schema_migrations/20181204154019
db/schema_migrations/20180103234731
db/schema_migrations/20180104001824
db/schema_migrations/20180105233807
db/schema_migrations/20180109150457
db/schema_migrations/20180115013218
db/schema_migrations/20180126165535
db/schema_migrations/20180131104538
db/schema_migrations/20180201101405
db/schema_migrations/20180201192230
db/schema_migrations/20180206184810
db/schema_migrations/20180215143644
db/schema_migrations/20180225180932
db/schema_migrations/20180302230551
db/schema_migrations/20180307164427
db/schema_migrations/20180308234102
db/schema_migrations/20180314174825
db/schema_migrations/20180317020334
db/schema_migrations/20180320142552
db/schema_migrations/20180325034910
db/schema_migrations/20180329230151
db/schema_migrations/20180401213713
db/schema_migrations/20180416112831
db/schema_migrations/20180416205949
db/schema_migrations/20180419031622
db/schema_migrations/20180419171038
db/schema_migrations/20180423165301
db/schema_migrations/20180502124117
db/schema_migrations/20180502125859
db/schema_migrations/20180503154922
db/schema_migrations/20180520211048
db/schema_migrations/20180524115107
db/schema_migrations/20180531031410
db/schema_migrations/20180531221734
db/schema_migrations/20180607154422
db/schema_migrations/20180607154516
db/schema_migrations/20180607154645
db/schema_migrations/20180612175636
db/schema_migrations/20180615152524
db/schema_migrations/20180621100024
db/schema_migrations/20180621100025
db/schema_migrations/20180623053658
db/schema_migrations/20180626171125
db/schema_migrations/20180702114215
db/schema_migrations/20180702181530
db/schema_migrations/20180709153607
db/schema_migrations/20180709183353
db/schema_migrations/20180709184533
db/schema_migrations/20180711014025
db/schema_migrations/20180711014026
db/schema_migrations/20180718100455
db/schema_migrations/20180719161844
db/schema_migrations/20180720082636
db/schema_migrations/20180720120716
db/schema_migrations/20180720120726
db/schema_migrations/20180720121404
db/schema_migrations/20180723023517
db/schema_migrations/20180723081631
db/schema_migrations/20180723134433
db/schema_migrations/20180724161450
db/schema_migrations/20180803001726
db/schema_migrations/20180803041220
db/schema_migrations/20180806145747
db/schema_migrations/20180823132905
db/schema_migrations/20180831134049
db/schema_migrations/20180831152625
db/schema_migrations/20180910104020
db/schema_migrations/20180910105100
db/schema_migrations/20180912113336
db/schema_migrations/20180917145556
db/schema_migrations/20180917171038
db/schema_migrations/20180917171533
db/schema_migrations/20180917171534
db/schema_migrations/20180917171535
db/schema_migrations/20180917213751
db/schema_migrations/20180917214204
db/schema_migrations/20180920043317
db/schema_migrations/20180924070647
db/schema_migrations/20180926101838
db/schema_migrations/20180926140319
db/schema_migrations/20180930171532
db/schema_migrations/20181001172126
db/schema_migrations/20181001172651
db/schema_migrations/20181004131020
db/schema_migrations/20181004131025
db/schema_migrations/20181012151642
db/schema_migrations/20181017131623
db/schema_migrations/20181022131445
db/schema_migrations/20181025000427
db/schema_migrations/20181025030732
db/schema_migrations/20181026085436
db/schema_migrations/20181028092114
db/schema_migrations/20181028092115
db/schema_migrations/20181105122803
db/schema_migrations/20181114163403
db/schema_migrations/20181121174028
db/schema_migrations/20181121175359
db/schema_migrations/20181123090058
db/schema_migrations/20181123100058
db/schema_migrations/20181126125616
db/schema_migrations/20181127130125
db/schema_migrations/20181127133629
db/schema_migrations/20181127203117
db/schema_migrations/20181201151856
db/schema_migrations/20181203154104
db/schema_migrations/20181204031328
db/schema_migrations/20181204031329
db/schema_migrations/20181204031330
db/schema_migrations/20181204031331
db/schema_migrations/20181204135519
db/schema_migrations/20181204135932
db/schema_migrations/20181205093951
db/schema_migrations/20181206121338
db/schema_migrations/20181220163029
db/schema_migrations/20181221135205
db/schema_migrations/20181228140935
db/schema_migrations/20190110200434
db/schema_migrations/20190111183834
db/schema_migrations/20190114040404
db/schema_migrations/20190114040405
db/schema_migrations/20190121140418
db/schema_migrations/20190121140658
db/schema_migrations/20190122101816
db/schema_migrations/20190123211816
db/schema_migrations/20190128104236
db/schema_migrations/20190128172533
db/schema_migrations/20190129013538
db/schema_migrations/20190130164903
db/schema_migrations/20190218031401
db/schema_migrations/20190218144405
db/schema_migrations/20190219134239
db/schema_migrations/20190219210244
db/schema_migrations/20190220112238
db/schema_migrations/20190222105948
db/schema_migrations/20190222110418
db/schema_migrations/20190225173106
db/schema_migrations/20190226154144
db/schema_migrations/20190228134845
db/schema_migrations/20190301095211
db/schema_migrations/20190301182031
db/schema_migrations/20190302144241
db/schema_migrations/20190304020812
db/schema_migrations/20190304223216
db/schema_migrations/20190304223220
db/schema_migrations/20190305162221
db/schema_migrations/20190318020549
db/schema_migrations/20190318021429
db/schema_migrations/20190318120957
db/schema_migrations/20190320162221
db/schema_migrations/20190321103531
db/schema_migrations/20190322145954
db/schema_migrations/20190327085945
db/schema_migrations/20190328210840
db/schema_migrations/20190401150745
db/schema_migrations/20190401150746
db/schema_migrations/20190402112450
db/schema_migrations/20180309215236
db/schema_migrations/20180314172513
db/schema_migrations/20180417102933
db/schema_migrations/20180502130136
db/schema_migrations/20180509091305
db/schema_migrations/20180605213516
db/schema_migrations/20180608150653
db/schema_migrations/20180618193715
db/schema_migrations/20180713171825
db/schema_migrations/20180815043102
db/schema_migrations/20180914195058
db/schema_migrations/20181014131030
db/schema_migrations/20181115140251
db/schema_migrations/20181116100917
db/schema_migrations/20181204040404
db/schema_migrations/20181206121340
db/schema_migrations/20181215161939
db/schema_migrations/20181220165848
db/schema_migrations/20190111231855
# Removed in ef1efa0f650
db/schema_migrations/20180406204716
db/schema_migrations/20180521171529
db/schema_migrations/20180831164904
# Removed in 28ac2d30498
db/schema_migrations/20180202111106
# Removed in b87dcc238a8
db/schema_migrations/20181218192239
# Removed in various revert commits
db/schema_migrations/20180115094742
db/schema_migrations/20180115113902
db/schema_migrations/20190107151029
db/schema_migrations/20190114184258
db/schema_migrations/20190228092516
db/schema_migrations/20190311132500
db/schema_migrations/20190311132527
db/schema_migrations/20190703001116
db/schema_migrations/20190703001120
db/schema_migrations/20190724091326
db/schema_migrations/20190801072937
db/schema_migrations/20191004134055
db/schema_migrations/20191029060358
db/schema_migrations/20191029061556
db/schema_migrations/20191220102807
db/schema_migrations/20200123092602
db/schema_migrations/20200123101859
db/schema_migrations/20200127111953
db/schema_migrations/20200127131953
db/schema_migrations/20200127141953
db/schema_migrations/20200127151953
db/schema_migrations/20200206111847
db/schema_migrations/20200214173000
db/schema_migrations/20200214174519
db/schema_migrations/20200214174607
db/schema_migrations/20200309105539
db/schema_migrations/20200615203153

View file

@ -7,6 +7,7 @@ stages:
- post-test - post-test
- review-prepare - review-prepare
- review - review
- dast
- qa - qa
- post-qa - post-qa
- pages - pages
@ -104,3 +105,4 @@ include:
- local: .gitlab/ci/yaml.gitlab-ci.yml - local: .gitlab/ci/yaml.gitlab-ci.yml
- local: .gitlab/ci/releases.gitlab-ci.yml - local: .gitlab/ci/releases.gitlab-ci.yml
- local: .gitlab/ci/notify.gitlab-ci.yml - local: .gitlab/ci/notify.gitlab-ci.yml
- local: .gitlab/ci/dast.gitlab-ci.yml

View file

@ -10,13 +10,13 @@
/doc/ @gl-docsteam /doc/ @gl-docsteam
/doc/administration/monitoring/ @aqualls /doc/administration/monitoring/ @aqualls
/doc/development/ @marcia @mjang1 /doc/development/ @marcia @mjang1
/doc/development/documentation/ @mikelewis /doc/development/documentation/ @cnorris
/doc/ci @marcel.amirault @sselhorn /doc/ci @marcel.amirault @sselhorn
/doc/operations @aqualls @eread /doc/operations @aqualls @eread
/doc/user/clusters @aqualls /doc/user/clusters @aqualls
/doc/user/infrastructure @aqualls /doc/user/infrastructure @aqualls
/doc/user/project/clusters @aqualls /doc/user/project/clusters @aqualls
/doc/.vale/ @marcel.amirault @eread @aqualls @mikelewis /doc/.vale/ @marcel.amirault @eread @aqualls @cnorris
[Docs Create] [Docs Create]
/doc/user/project/merge_requests/allow_collaboration.md @marcia /doc/user/project/merge_requests/allow_collaboration.md @marcia
@ -165,12 +165,15 @@
/.gitlab/ci/ @gl-quality/eng-prod /.gitlab/ci/ @gl-quality/eng-prod
/.gitlab/ci/docs.gitlab-ci.yml @gl-quality/eng-prod @gl-docsteam /.gitlab/ci/docs.gitlab-ci.yml @gl-quality/eng-prod @gl-docsteam
/.gitlab/ci/releases.gitlab-ci.yml @gl-quality/eng-prod @gitlab-org/delivery /.gitlab/ci/releases.gitlab-ci.yml @gl-quality/eng-prod @gitlab-org/delivery
/.gitlab/ci/dast.gitlab-ci.yml @dappelt @ngeorge1 @gl-quality/eng-prod
/.gitlab/ci/reports.gitlab-ci.yml @gitlab-com/gl-security/appsec @gl-quality/eng-prod
/.gitlab/CODEOWNERS @gl-quality/eng-prod /.gitlab/CODEOWNERS @gl-quality/eng-prod
Dangerfile @gl-quality/eng-prod Dangerfile @gl-quality/eng-prod
/danger/ @gl-quality/eng-prod /danger/ @gl-quality/eng-prod
/lib/gitlab/danger/ @gl-quality/eng-prod /lib/gitlab/danger/ @gl-quality/eng-prod
/scripts/ @gl-quality/eng-prod /scripts/ @gl-quality/eng-prod
/scripts/frontend/ @gl-quality/eng-prod @gitlab-org/maintainers/frontend /scripts/frontend/ @gl-quality/eng-prod @gitlab-org/maintainers/frontend
/scripts/review_apps/seed-dast-test-data.sh @dappelt @ngeorge1 @gl-quality/eng-prod
.editorconfig @gl-quality/eng-prod .editorconfig @gl-quality/eng-prod
[End-to-end] [End-to-end]
@ -192,9 +195,11 @@ Dangerfile @gl-quality/eng-prod
# Secure & Threat Management ownership delineation # Secure & Threat Management ownership delineation
# https://about.gitlab.com/handbook/engineering/development/threat-management/delineate-secure-threat-management.html#technical-boundaries # https://about.gitlab.com/handbook/engineering/development/threat-management/delineate-secure-threat-management.html#technical-boundaries
[Secure] [Secure]
/ee/app/models/vulnerability.rb @gitlab-org/secure/threat-insights-backend-team /ee/app/finders/security/ @gitlab-org/secure/threat-insights-backend-team
/ee/app/models/security/ @gitlab-org/secure/threat-insights-backend-team /ee/app/models/security/ @gitlab-org/secure/threat-insights-backend-team
/ee/app/models/vulnerabilities/ @gitlab-org/secure/threat-insights-backend-team /ee/app/models/vulnerabilities/ @gitlab-org/secure/threat-insights-backend-team
/ee/app/models/vulnerability.rb @gitlab-org/secure/threat-insights-backend-team
/ee/lib/api/vulnerabilit*.rb @gitlab-org/secure/threat-insights-backend-team
/ee/lib/gitlab/ci/parsers/license_compliance/ @gitlab-org/secure/composition-analysis-be /ee/lib/gitlab/ci/parsers/license_compliance/ @gitlab-org/secure/composition-analysis-be
/ee/lib/gitlab/ci/parsers/security/ @gitlab-org/secure/composition-analysis-be @gitlab-org/secure/dynamic-analysis-be @gitlab-org/secure/static-analysis-be @gitlab-org/secure/fuzzing-be /ee/lib/gitlab/ci/parsers/security/ @gitlab-org/secure/composition-analysis-be @gitlab-org/secure/dynamic-analysis-be @gitlab-org/secure/static-analysis-be @gitlab-org/secure/fuzzing-be
/ee/lib/gitlab/ci/reports/coverage_fuzzing/ @gitlab-org/secure/fuzzing-be /ee/lib/gitlab/ci/reports/coverage_fuzzing/ @gitlab-org/secure/fuzzing-be

View file

@ -0,0 +1,203 @@
.dast_conf:
tags:
- prm
# For scheduling dast job
extends:
- .reports:schedule-dast
image:
name: "registry.gitlab.com/gitlab-org/security-products/dast:$DAST_VERSION"
resource_group: dast_scan
variables:
DAST_USERNAME_FIELD: "user[login]"
DAST_PASSWORD_FIELD: "user[password]"
DAST_FULL_SCAN_ENABLED: "true"
DAST_SPIDER_MINS: 0
# TBD pin to a version
DAST_VERSION: 1.22.1
# -Xmx is used to set the JVM memory to 6GB to prevent DAST OutOfMemoryError.
DAST_ZAP_CLI_OPTIONS: "-Xmx6144m"
DAST_RULES: "41,42,43,10027,10032,10041,10042,10045,10047,10052,10053,10057,10061,10096,10097,10104,10106,20012,20014,20015,20016,20017,20018,40019,40020,40021,40024,40025,40027,40029,40032,90001,90019,10109,10026,10028,10029,10030,10031,10033,10034,10035,10036,10038,10039,10043,10044,10048,10050,10051,10058,10062,10095,10107,10108,30003,40013,40022,40023,40028,90021,90023,90024,90025,90027,90028,10003,50003,0,2,3,6,7,10010,10011,10015,10017,10019,10020,10021,10023,10024,10025,10037,10040,10054,10055,10056,10098,10105,10202,20019,30001,30002,40003,40008,40009,40012,40014,40016,40017,40018,50000,50001,90011,90020,90022,90033"
before_script:
- 'export DAST_WEBSITE="${DAST_WEBSITE:-$(cat environment_url.txt)}"'
- 'export DAST_AUTH_URL="${DAST_WEBSITE}/users/sign_in"'
- 'export DAST_PASSWORD="${REVIEW_APPS_ROOT_PASSWORD}"'
# Below three lines can be removed once https://gitlab.com/gitlab-org/gitlab/-/issues/230687 is fixed
- mkdir -p /zap/xml
- 'sed -i "84 s/true/false/" /zap/xml/config.xml'
- cat /zap/xml/config.xml
# Help pages are excluded from scan as they are static pages.
# profile/two_factor_auth is excluded from scan to prevent 2FA from being turned on from user profile, which will reduce coverage.
- 'export DAST_AUTH_EXCLUDE_URLS="${DAST_WEBSITE}/help/.*,${DAST_WEBSITE}/profile/two_factor_auth,${DAST_WEBSITE}/users/sign_out"'
- enable_rule () { read all_rules; rule=$1; echo $all_rules | sed -r "s/(,)?$rule(,)?/\1-1\2/" ; }
# Sort ids in DAST_RULES ascendingly, which is required when using DAST_RULES as argument to enable_rule
- 'DAST_RULES=$(echo $DAST_RULES | tr "," "\n" | sort -n | paste -sd ",")'
needs: ["review-deploy"]
stage: dast
# Default job timeout set to 90m and dast rules needs 2h to so that it won't timeout.
timeout: 2h
# Add retry because of intermittent connection problems. See https://gitlab.com/gitlab-org/gitlab/-/issues/244313
retry: 1
artifacts:
paths:
- gl-dast-report.json # GitLab-specific
reports:
dast: gl-dast-report.json
expire_in: 1 week # GitLab-specific
# DAST scan with a subset of Release scan rules.
DAST-fullscan-ruleset1:
extends:
- .dast_conf
variables:
DAST_USERNAME: "user1"
script:
- export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 10019 | enable_rule 10020 | enable_rule 10021 | enable_rule 10023 | enable_rule 10024 | enable_rule 10025 | enable_rule 10037 | enable_rule 10040 | enable_rule 10054 | enable_rule 10055 | enable_rule 10056)
- echo $DAST_EXCLUDE_RULES
- /analyze -t $DAST_WEBSITE -d
# DAST scan with a subset of Release scan rules.
DAST-fullscan-ruleset2:
extends:
- .dast_conf
variables:
DAST_USERNAME: "user2"
script:
- export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 90011 | enable_rule 90020 | enable_rule 90022 | enable_rule 90033)
- echo $DAST_EXCLUDE_RULES
- /analyze -t $DAST_WEBSITE -d
# DAST scan with a subset of Release scan rules.
DAST-fullscan-ruleset3:
extends:
- .dast_conf
variables:
DAST_USERNAME: "user3"
script:
- export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 40016 | enable_rule 40017 | enable_rule 50000 | enable_rule 50001)
- echo $DAST_EXCLUDE_RULES
- /analyze -t $DAST_WEBSITE -d
# DAST scan with a subset of Release scan rules.
DAST-fullscan-ruleset4:
extends:
- .dast_conf
variables:
DAST_USERNAME: "user4"
script:
- export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 0 | enable_rule 2 | enable_rule 3 | enable_rule 7 )
- echo $DAST_EXCLUDE_RULES
- /analyze -t $DAST_WEBSITE -d
# DAST scan with a subset of Release scan rules.
DAST-fullscan-ruleset5:
extends:
- .dast_conf
variables:
DAST_USERNAME: "user5"
script:
- export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 10010 | enable_rule 10011 | enable_rule 10015 | enable_rule 10017 | enable_rule 10019)
- echo $DAST_EXCLUDE_RULES
- /analyze -t $DAST_WEBSITE -d
# DAST scan with a subset of Release scan rules.
DAST-fullscan-ruleset6:
extends:
- .dast_conf
variables:
DAST_USERNAME: "user6"
script:
- export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 30001 | enable_rule 40009)
- echo $DAST_EXCLUDE_RULES
- /analyze -t $DAST_WEBSITE -d
# Enable when https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39749 is fixed
# DAST scan with a subset of Beta scan rules.
# DAST-fullscan-ruleset7:
# extends:
# - .dast_conf
# variables:
# DAST_USERNAME: "user7"
# script:
# - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 10098 | enable_rule 10105 | enable_rule 10202 | enable_rule 30002 | enable_rule 40003 | enable_rule 40008 | enable_rule 40009)
# - echo $DAST_EXCLUDE_RULES
# - /analyze -t $DAST_WEBSITE -d
# Enable when https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39749 is fixed
# Below jobs runs DAST scans with one time consuming scan rule. These scan rules are disabled in above jobs so that those jobs won't timeout.
# DAST scan with rule - 20019 External Redirect
# DAST-fullscan-rule-20019:
# extends:
# - .dast_conf
# variables:
# DAST_USERNAME: "user8"
# script:
# - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 20019)
# - echo $DAST_EXCLUDE_RULES
# - /analyze -t $DAST_WEBSITE -d
# Enable when https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39749 is fixed
# DAST scan with rule - 10107 Httpoxy - Proxy Header Misuse - Active/beta
# DAST-fullscan-rule-10107:
# extends:
# - .dast_conf
# variables:
# DAST_USERNAME: "user9"
# script:
# - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 10107)
# - echo $DAST_EXCLUDE_RULES
# - /analyze -t $DAST_WEBSITE -d
# DAST scan with rule - 90020 Remote OS Command Injection
DAST-fullscan-rule-90020:
extends:
- .dast_conf
variables:
DAST_USERNAME: "user10"
script:
- export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 90020)
- echo $DAST_EXCLUDE_RULES
- /analyze -t $DAST_WEBSITE -d
# DAST scan with rule - 40018 SQL Injection - Active/release
DAST-fullscan-rule-40018:
extends:
- .dast_conf
variables:
DAST_USERNAME: "user11"
script:
- export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 40018)
- echo $DAST_EXCLUDE_RULES
- /analyze -t $DAST_WEBSITE -d
# DAST scan with rule - 40014 Cross Site Scripting (Persistent) - Active/release
DAST-fullscan-rule-40014:
extends:
- .dast_conf
variables:
DAST_USERNAME: "user12"
script:
- export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 40014)
- echo $DAST_EXCLUDE_RULES
- /analyze -t $DAST_WEBSITE -d
# DAST scan with rule - 6 Path travesal
DAST-fullscan-rule-6:
extends:
- .dast_conf
variables:
DAST_USERNAME: "user13"
script:
- export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 6)
- echo $DAST_EXCLUDE_RULES
- /analyze -t $DAST_WEBSITE -d
# DAST scan with rule - 40012 Cross Site Scripting (Reflected)
DAST-fullscan-rule-40012:
extends:
- .dast_conf
variables:
DAST_USERNAME: "user14"
script:
- export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 40012)
- echo $DAST_EXCLUDE_RULES
- /analyze -t $DAST_WEBSITE -d

View file

@ -42,7 +42,7 @@ docs lint:
extends: extends:
- .default-retry - .default-retry
- .docs:rules:docs-lint - .docs:rules:docs-lint
image: "registry.gitlab.com/gitlab-org/gitlab-docs:lint" image: "registry.gitlab.com/gitlab-org/gitlab-docs/lint:vale-2.3.4-markdownlint-0.23.2"
stage: test stage: test
needs: [] needs: []
script: script:

View file

@ -10,7 +10,7 @@ notify-update-gitaly:
extends: extends:
- .notify-slack - .notify-slack
rules: rules:
- if: '$CI_MERGE_REQUEST_IID && $CI_COMMIT_BRANCH == $GITALY_UPDATE_BRANCH' - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == $GITALY_UPDATE_BRANCH'
when: on_failure when: on_failure
allow_failure: true allow_failure: true
variables: variables:

View file

@ -296,6 +296,21 @@ gitlab:setup:
paths: paths:
- log/*.log - log/*.log
db:backup_and_restore:
extends: .db-job-base
variables:
SETUP_DB: "false"
GITLAB_ASSUME_YES: "1"
script:
- . scripts/prepare_build.sh
- bundle exec rake db:drop db:create db:structure:load db:seed_fu
- mkdir -p tmp/tests/public/uploads tmp/tests/{artifacts,pages,lfs-objects,registry}
- bundle exec rake gitlab:backup:create
- date
- bundle exec rake gitlab:backup:restore
rules:
- changes: ["lib/backup/**/*"]
rspec:coverage: rspec:coverage:
extends: extends:
- .rails-job-base - .rails-job-base
@ -490,21 +505,50 @@ rspec-ee system pg12 geo:
################################################## ##################################################
# EE: Canonical MR pipelines # EE: Canonical MR pipelines
rspec foss-impact: rspec fail-fast:
extends: extends:
- .rspec-base-pg11-as-if-foss - .rspec-ee-base-pg11 # This job also runs EE spec which needs elasticsearch
- .rails:rules:ee-mr-only - .rails:rules:rspec fail-fast
stage: test
needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets", "detect-tests"]
script: script:
- install_gitlab_gem
- run_timed_command "scripts/gitaly-test-build" - run_timed_command "scripts/gitaly-test-build"
- run_timed_command "scripts/gitaly-test-spawn" - run_timed_command "scripts/gitaly-test-spawn"
- source scripts/rspec_helpers.sh - source scripts/rspec_helpers.sh
- tooling/bin/find_foss_tests tmp/matching_foss_tests.txt - rspec_fail_fast tmp/matching_tests.txt "--tag ~quarantine"
- rspec_matched_tests tmp/matching_foss_tests.txt "--tag ~quarantine"
artifacts: artifacts:
expire_in: 7d expire_in: 7d
paths: paths:
- tmp/matching_foss_tests.txt
- tmp/capybara/ - tmp/capybara/
rspec foss-impact:
extends:
- .rspec-base-pg11-as-if-foss
- .rails:rules:rspec-foss-impact
needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets as-if-foss", "detect-tests as-if-foss"]
script:
- run_timed_command "scripts/gitaly-test-build"
- run_timed_command "scripts/gitaly-test-spawn"
- source scripts/rspec_helpers.sh
- rspec_matched_foss_tests tmp/matching_foss_tests.txt "--tag ~quarantine"
artifacts:
expire_in: 7d
paths:
- tmp/capybara/
fail-pipeline-early:
extends:
- .rails:rules:fail-pipeline-early
stage: post-test
needs:
- job: rspec fail-fast
artifacts: false
variables:
GIT_DEPTH: 1
before_script:
- source scripts/utils.sh
- install_api_client_dependencies_with_apt
script:
- fail_pipeline_early
# EE: Canonical MR pipelines # EE: Canonical MR pipelines
################################################## ##################################################

View file

@ -81,7 +81,13 @@ nodejs-scan-sast:
secrets-sast: secrets-sast:
extends: .sast extends: .sast
image: image:
name: "$SAST_ANALYZER_IMAGE_PREFIX/secrets:$SAST_ANALYZER_IMAGE_TAG" name: "$SAST_ANALYZER_IMAGE_PREFIX/secrets:3"
artifacts:
paths:
- gl-secret-detection-report.json # GitLab-specific
reports:
sast: gl-secret-detection-report.json
expire_in: 1 week # GitLab-specific
# We need to duplicate this job's definition because it seems it's impossible to # We need to duplicate this job's definition because it seems it's impossible to
# override an included `only.refs`. # override an included `only.refs`.
@ -145,45 +151,3 @@ dependency_scanning:
reports: reports:
dependency_scanning: gl-dependency-scanning-report.json dependency_scanning: gl-dependency-scanning-report.json
expire_in: 1 week # GitLab-specific expire_in: 1 week # GitLab-specific
# Temporarily disabling review apps
## We need to duplicate this job's definition because it seems it's impossible to
## override an included `only.refs`.
## See https://gitlab.com/gitlab-org/gitlab/issues/31371.
# dast:
# extends:
# - .default-retry
# - .reports:rules:dast
# # This is needed so that manual jobs with needs don't block the pipeline.
# # See https://gitlab.com/gitlab-org/gitlab/-/issues/199979.
# dependencies: ["review-deploy"]
# stage: qa # GitLab-specific
# image:
# name: "registry.gitlab.com/gitlab-org/security-products/dast:$DAST_VERSION"
# variables:
# # To be done in a later iteration
# # DAST_USERNAME: "root"
# # DAST_USERNAME_FIELD: "user[login]"
# # DAST_PASSWORD_FIELD: "user[passowrd]"
# DAST_VERSION: 1
# script:
# - 'export DAST_WEBSITE="${DAST_WEBSITE:-$(cat environment_url.txt)}"'
# # To be done in a later iteration
# # - 'export DAST_AUTH_URL="${DAST_WEBSITE}/users/sign_in"'
# # - 'export DAST_PASSWORD="${REVIEW_APPS_ROOT_PASSWORD}"'
# - /analyze -t $DAST_WEBSITE
# timeout: 4h
# artifacts:
# paths:
# - gl-dast-report.json # GitLab-specific
# reports:
# dast: gl-dast-report.json
# expire_in: 1 week # GitLab-specific
# To be done in a later iteration: https://gitlab.com/gitlab-org/gitlab/issues/31160#note_278188255
# schedule:dast:
# extends:
# - dast
# - .reports:schedule-dast
# variables:
# DAST_FULL_SCAN_ENABLED: "true"

View file

@ -43,9 +43,9 @@ review-build-cng:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}" HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
REVIEW_APPS_DOMAIN: "temp.gitlab-review.app" # FIXME: using temporary domain REVIEW_APPS_DOMAIN: "temp.gitlab-review.app" # FIXME: using temporary domain
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}" DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
GITLAB_HELM_CHART_REF: "v4.1.3" GITLAB_HELM_CHART_REF: "v4.3.0"
environment: environment:
name: review/${CI_COMMIT_REF_NAME} name: review/${CI_COMMIT_REF_SLUG}${FREQUENCY}
url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN} url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}
on_stop: review-stop on_stop: review-stop
auto_stop_in: 48 hours auto_stop_in: 48 hours
@ -53,7 +53,7 @@ review-build-cng:
review-deploy: review-deploy:
extends: extends:
- .review-workflow-base - .review-workflow-base
- .review:rules:mr-and-schedule-auto-if-frontend-manual-otherwise - .review:rules:review-deploy
stage: review stage: review
dependencies: [] dependencies: []
resource_group: "review/${CI_COMMIT_REF_NAME}" resource_group: "review/${CI_COMMIT_REF_NAME}"
@ -77,6 +77,11 @@ review-deploy:
# to have to manually start the jobs in sequence, so we do it for them. # to have to manually start the jobs in sequence, so we do it for them.
- '[ -z $CI_JOB_MANUAL ] || play_job "review-qa-smoke"' - '[ -z $CI_JOB_MANUAL ] || play_job "review-qa-smoke"'
- '[ -z $CI_JOB_MANUAL ] || play_job "review-performance"' - '[ -z $CI_JOB_MANUAL ] || play_job "review-performance"'
after_script:
# Run seed-dast-test-data.sh only when DAST_RUN is set to true. This is to pupulate review app with data for DAST scan.
# Set DAST_RUN to true when jobs are manually scheduled.
- if [ "$DAST_RUN" == "true" ]; then source scripts/review_apps/seed-dast-test-data.sh; TRACE=1 trigger_proj_user_creation; fi
artifacts: artifacts:
paths: [environment_url.txt] paths: [environment_url.txt]
expire_in: 2 days expire_in: 2 days
@ -108,8 +113,8 @@ review-stop-failed-deployment:
review-stop: review-stop:
extends: extends:
- .review-stop-base - .review-stop-base
- .review:rules:mr-only-manual - .review:rules:review-stop
stage: review stage: post-qa
script: script:
- delete_release - delete_release
@ -167,7 +172,7 @@ review-qa-all:
review-performance: review-performance:
extends: extends:
- .default-retry - .default-retry
- .review:rules:mr-and-schedule-auto-if-frontend-manual-otherwise - .review:rules:review-performance
image: image:
name: sitespeedio/sitespeed.io:6.3.1 name: sitespeedio/sitespeed.io:6.3.1
entrypoint: [""] entrypoint: [""]

View file

@ -67,6 +67,12 @@
.if-cache-credentials-schedule: &if-cache-credentials-schedule .if-cache-credentials-schedule: &if-cache-credentials-schedule
if: '$CI_REPO_CACHE_CREDENTIALS && $CI_PIPELINE_SOURCE == "schedule"' if: '$CI_REPO_CACHE_CREDENTIALS && $CI_PIPELINE_SOURCE == "schedule"'
.if-rspec-fail-fast-disabled: &if-rspec-fail-fast-disabled
if: '$RSPEC_FAIL_FAST_ENABLED != "true"'
.if-rspec-fail-fast-skipped: &if-rspec-fail-fast-skipped
if: '$CI_MERGE_REQUEST_TITLE =~ /SKIP RSPEC FAIL-FAST/'
#################### ####################
# Changes patterns # # Changes patterns #
#################### ####################
@ -83,6 +89,7 @@
- ".gitlab/ci/frontend.gitlab-ci.yml" - ".gitlab/ci/frontend.gitlab-ci.yml"
- ".gitlab/ci/build-images.gitlab-ci.yml" - ".gitlab/ci/build-images.gitlab-ci.yml"
- ".gitlab/ci/review.gitlab-ci.yml" - ".gitlab/ci/review.gitlab-ci.yml"
- "scripts/trigger-build"
.ci-qa-patterns: &ci-qa-patterns .ci-qa-patterns: &ci-qa-patterns
- ".gitlab-ci.yml" - ".gitlab-ci.yml"
@ -121,11 +128,13 @@
- "{,ee/}spec/**/*.rb" - "{,ee/}spec/**/*.rb"
- ".gitlab-ci.yml" - ".gitlab-ci.yml"
- ".gitlab/ci/**/*" - ".gitlab/ci/**/*"
- "*_VERSION"
.db-patterns: &db-patterns .db-patterns: &db-patterns
- "{,ee/}{,spec/}{db,migrations}/**/*" - "{,ee/}{,spec/}{db,migrations}/**/*"
- "{,ee/}{,spec/}lib/{,ee/}gitlab/background_migration/**/*" - "{,ee/}{,spec/}lib/{,ee/}gitlab/background_migration/**/*"
- "config/prometheus/common_metrics.yml" # Used by Gitlab::DatabaseImporters::CommonMetrics::Importer - "config/prometheus/common_metrics.yml" # Used by Gitlab::DatabaseImporters::CommonMetrics::Importer
- "{,ee/}app/models/project_statistics.rb" # Used to calculate sizes in migration specs
.backstage-patterns: &backstage-patterns .backstage-patterns: &backstage-patterns
- "Dangerfile" - "Dangerfile"
@ -147,6 +156,7 @@
- "*_VERSION" - "*_VERSION"
- "Gemfile{,.lock}" - "Gemfile{,.lock}"
- "Rakefile" - "Rakefile"
- "tests.yml"
- "config.ru" - "config.ru"
- "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*" - "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated - "doc/api/graphql/reference/*" # Files in this folder are auto-generated
@ -168,6 +178,7 @@
- "*_VERSION" - "*_VERSION"
- "Gemfile{,.lock}" - "Gemfile{,.lock}"
- "Rakefile" - "Rakefile"
- "tests.yml"
- "config.ru" - "config.ru"
- "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*" - "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated - "doc/api/graphql/reference/*" # Files in this folder are auto-generated
@ -191,6 +202,7 @@
- "*_VERSION" - "*_VERSION"
- "Gemfile{,.lock}" - "Gemfile{,.lock}"
- "Rakefile" - "Rakefile"
- "tests.yml"
- "config.ru" - "config.ru"
- "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*" - "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated - "doc/api/graphql/reference/*" # Files in this folder are auto-generated
@ -211,6 +223,7 @@
- "*_VERSION" - "*_VERSION"
- "Gemfile{,.lock}" - "Gemfile{,.lock}"
- "Rakefile" - "Rakefile"
- "tests.yml"
- "config.ru" - "config.ru"
- "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*" - "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated - "doc/api/graphql/reference/*" # Files in this folder are auto-generated
@ -506,6 +519,7 @@
- <<: *if-security-merge-request - <<: *if-security-merge-request
changes: *db-patterns changes: *db-patterns
- <<: *if-merge-request-title-as-if-foss - <<: *if-merge-request-title-as-if-foss
changes: *db-patterns
- <<: *if-merge-request - <<: *if-merge-request
changes: *ci-patterns changes: *ci-patterns
@ -516,6 +530,7 @@
- <<: *if-security-merge-request - <<: *if-security-merge-request
changes: *backend-patterns changes: *backend-patterns
- <<: *if-merge-request-title-as-if-foss - <<: *if-merge-request-title-as-if-foss
changes: *backend-patterns
- <<: *if-merge-request - <<: *if-merge-request
changes: *ci-patterns changes: *ci-patterns
@ -526,6 +541,7 @@
- <<: *if-security-merge-request - <<: *if-security-merge-request
changes: *backend-patterns changes: *backend-patterns
- <<: *if-merge-request-title-as-if-foss - <<: *if-merge-request-title-as-if-foss
changes: *backend-patterns
- <<: *if-merge-request - <<: *if-merge-request
changes: *ci-patterns changes: *ci-patterns
@ -536,6 +552,7 @@
- <<: *if-security-merge-request - <<: *if-security-merge-request
changes: *code-backstage-patterns changes: *code-backstage-patterns
- <<: *if-merge-request-title-as-if-foss - <<: *if-merge-request-title-as-if-foss
changes: *code-backstage-patterns
- <<: *if-merge-request - <<: *if-merge-request
changes: *ci-patterns changes: *ci-patterns
@ -549,7 +566,16 @@
- <<: *if-master-refs - <<: *if-master-refs
changes: *code-backstage-patterns changes: *code-backstage-patterns
.rails:rules:ee-mr-only: .rails:rules:detect-tests:
rules:
- <<: *if-not-ee
when: never
- <<: *if-security-merge-request
changes: *code-backstage-patterns
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-backstage-patterns
.rails:rules:rspec-foss-impact:
rules: rules:
- <<: *if-not-ee - <<: *if-not-ee
when: never when: never
@ -560,6 +586,34 @@
- <<: *if-dot-com-gitlab-org-merge-request - <<: *if-dot-com-gitlab-org-merge-request
changes: *code-backstage-patterns changes: *code-backstage-patterns
.rails:rules:rspec fail-fast:
rules:
- <<: *if-rspec-fail-fast-disabled
when: never
- <<: *if-rspec-fail-fast-skipped
when: never
- <<: *if-not-ee
when: never
- <<: *if-security-merge-request
changes: *code-backstage-patterns
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-backstage-patterns
.rails:rules:fail-pipeline-early:
rules:
- <<: *if-rspec-fail-fast-disabled
when: never
- <<: *if-rspec-fail-fast-skipped
when: never
- <<: *if-not-ee
when: never
- <<: *if-security-merge-request
changes: *code-backstage-patterns
when: on_failure
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-backstage-patterns
when: on_failure
.rails:rules:downtime_check: .rails:rules:downtime_check:
rules: rules:
- <<: *if-merge-request - <<: *if-merge-request
@ -569,6 +623,8 @@
rules: rules:
- <<: *if-not-ee - <<: *if-not-ee
when: never when: never
- <<: *if-merge-request
changes: *code-backstage-patterns
- <<: *if-master-schedule-2-hourly - <<: *if-master-schedule-2-hourly
- <<: *if-merge-request-title-run-all-rspec - <<: *if-merge-request-title-run-all-rspec
@ -643,7 +699,8 @@
rules: rules:
- if: '$DAST_DISABLED || $GITLAB_FEATURES !~ /\bdast\b/' - if: '$DAST_DISABLED || $GITLAB_FEATURES !~ /\bdast\b/'
when: never when: never
- <<: *if-dot-com-gitlab-org-schedule - <<: *if-master-schedule-nightly
allow_failure: true
################ ################
# Review rules # # Review rules #
@ -662,7 +719,7 @@
allow_failure: true allow_failure: true
- <<: *if-dot-com-gitlab-org-schedule - <<: *if-dot-com-gitlab-org-schedule
.review:rules:mr-and-schedule-auto-if-frontend-manual-otherwise: .review:rules:review-deploy:
rules: rules:
- <<: *if-not-ee - <<: *if-not-ee
when: never when: never
@ -678,6 +735,24 @@
- <<: *if-dot-com-gitlab-org-schedule - <<: *if-dot-com-gitlab-org-schedule
allow_failure: true allow_failure: true
.review:rules:review-performance:
rules:
- if: '$DAST_RUN == "true"' # Skip this job when DAST is run
when: never
- <<: *if-not-ee
when: never
- <<: *if-dot-com-gitlab-org-merge-request
changes: *ci-review-patterns
- <<: *if-dot-com-gitlab-org-merge-request
changes: *frontend-patterns
allow_failure: true
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-qa-patterns
when: manual
allow_failure: true
- <<: *if-dot-com-gitlab-org-schedule
allow_failure: true
.review:rules:review-stop-failed-deployment: .review:rules:review-stop-failed-deployment:
rules: rules:
- <<: *if-not-ee - <<: *if-not-ee
@ -719,6 +794,17 @@
- <<: *if-dot-com-gitlab-org-schedule - <<: *if-dot-com-gitlab-org-schedule
allow_failure: true allow_failure: true
.review:rules:review-stop:
rules:
- <<: *if-not-ee
when: never
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-qa-patterns
when: manual
allow_failure: true
- <<: *if-dot-com-gitlab-org-schedule
allow_failure: true
.review:rules:danger: .review:rules:danger:
rules: rules:
- if: '$DANGER_GITLAB_API_TOKEN && $CI_MERGE_REQUEST_IID' - if: '$DANGER_GITLAB_API_TOKEN && $CI_MERGE_REQUEST_IID'
@ -757,6 +843,14 @@
changes: *code-backstage-patterns changes: *code-backstage-patterns
when: on_success when: on_success
.setup:rules:verify-tests-yml:
rules:
- <<: *if-not-ee
when: never
- <<: *if-default-refs
changes: *code-backstage-patterns
when: on_success
####################### #######################
# Test metadata rules # # Test metadata rules #
####################### #######################

View file

@ -48,3 +48,46 @@ no_ee_check:
stage: test stage: test
script: script:
- scripts/no-ee-check - scripts/no-ee-check
verify-tests-yml:
extends:
- .setup:rules:verify-tests-yml
image: ruby:2.6-alpine
stage: test
needs: []
script:
- source scripts/utils.sh
- install_tff_gem
- scripts/verify-tff-mapping
.detect-test-base:
image: ruby:2.6-alpine
needs: []
stage: prepare
script:
- source scripts/utils.sh
- install_gitlab_gem
- install_tff_gem
- tooling/bin/find_foss_tests ${MATCHED_TESTS_FILE}
- 'echo "test files affected: $(cat $MATCHED_TESTS_FILE)"'
artifacts:
expire_in: 7d
paths:
- ${MATCHED_TESTS_FILE}
detect-tests:
extends:
- .detect-test-base
- .rails:rules:detect-tests
variables:
MATCHED_TESTS_FILE: tmp/matching_tests.txt
detect-tests as-if-foss:
extends:
- .detect-test-base
- .rails:rules:detect-tests
- .as-if-foss
variables:
MATCHED_TESTS_FILE: tmp/matching_foss_tests.txt
before_script:
- '[ "$FOSS_ONLY" = "1" ] && rm -rf ee/ qa/spec/ee/ qa/qa/specs/features/ee/ qa/qa/ee/ qa/qa/ee.rb'

View file

@ -12,37 +12,39 @@ and verify the issue you're about to submit isn't a duplicate.
### Summary ### Summary
(Summarize the bug encountered concisely) <!-- Summarize the bug encountered concisely. -->
### Steps to reproduce ### Steps to reproduce
(How one can reproduce the issue - this is very important) <!-- Describe how one can reproduce the issue - this is very important. Please use an ordered list. -->
### Example Project ### Example Project
(If possible, please create an example project here on GitLab.com that exhibits the problematic behavior, and link to it here in the bug report) <!-- If possible, please create an example project here on GitLab.com that exhibits the problematic
behavior, and link to it here in the bug report. If you are using an older version of GitLab, this
(If you are using an older version of GitLab, this will also determine whether the bug is fixed in a more recent version) will also determine whether the bug is fixed in a more recent version. -->
### What is the current *bug* behavior? ### What is the current *bug* behavior?
(What actually happens) <!-- Describe what actually happens. -->
### What is the expected *correct* behavior? ### What is the expected *correct* behavior?
(What you should see instead) <!-- Describe what you should see instead. -->
### Relevant logs and/or screenshots ### Relevant logs and/or screenshots
(Paste any relevant logs - please use code blocks (```) to format console output, <!-- Paste any relevant logs - please use code blocks (```) to format console output, logs, and code
logs, and code as it's tough to read otherwise.) as it's tough to read otherwise. -->
### Output of checks ### Output of checks
(If you are reporting a bug on GitLab.com, write: This bug happens on GitLab.com) <!-- If you are reporting a bug on GitLab.com, write: This bug happens on GitLab.com -->
#### Results of GitLab environment info #### Results of GitLab environment info
<!-- Input any relevant GitLab environment information if needed. -->
<details> <details>
<summary>Expand for output related to GitLab environment info</summary> <summary>Expand for output related to GitLab environment info</summary>
@ -59,6 +61,8 @@ logs, and code as it's tough to read otherwise.)
#### Results of GitLab application Check #### Results of GitLab application Check
<!-- Input any relevant GitLab application check information if needed. -->
<details> <details>
<summary>Expand for output related to the GitLab application check</summary> <summary>Expand for output related to the GitLab application check</summary>
<pre> <pre>
@ -76,6 +80,6 @@ logs, and code as it's tough to read otherwise.)
### Possible fixes ### Possible fixes
(If you can, link to the line of code that might be responsible for the problem) <!-- If you can, link to the line of code that might be responsible for the problem. -->
/label ~bug /label ~bug

View file

@ -1,4 +1,8 @@
<!-- The first four sections: "Problem to solve", "Intended users", "User experience goal", and "Proposal", are strongly recommended, while the rest of the sections can be filled out during the problem validation or breakdown phase. However, keep in mind that providing complete and relevant information early helps our product team validate the problem and start working on a solution. --> <!-- The first section "Release notes" is required if you want to have your release post blog MR auto generated. Currently in BETA, details on the **release post item generator** can be found in the handbook: https://about.gitlab.com/handbook/marketing/blog/release-posts/#release-post-item-generator and this video: https://www.youtube.com/watch?v=rfn9ebgTwKg. The next four sections: "Problem to solve", "Intended users", "User experience goal", and "Proposal", are strongly recommended in your first draft, while the rest of the sections can be filled out during the problem validation or breakdown phase. However, keep in mind that providing complete and relevant information early helps our product team validate the problem and start working on a solution. -->
### Release notes
<!-- What is the problem and solution you're proposing? This content sets the overall vision for the feature and serves as the release notes that will populate in various places, including the [release post blog](https://about.gitlab.com/releases/categories/releases/) and [Gitlab project releases](https://gitlab.com/gitlab-org/gitlab/-/releases). " -->
### Problem to solve ### Problem to solve

View file

@ -68,10 +68,10 @@ a nightly pipeline, select ~"found:nightly".
<!-- <!--
https://about.gitlab.com/handbook/engineering/quality/guidelines/#priorities: https://about.gitlab.com/handbook/engineering/quality/guidelines/#priorities:
- ~P::1: Tests that are needed to verify fundamental GitLab functionality. - ~"priority::1": Tests that are needed to verify fundamental GitLab functionality.
- ~P::2: Tests that deal with external integrations which may take a longer time to debug and fix. - ~"priority::2": Tests that deal with external integrations which may take a longer time to debug and fix.
--> -->
/label ~P:: /label ~priority::
<!-- Select the current milestone if ~P::1 or the next milestone if ~P::2. --> <!-- Select the current milestone if ~"priority::1" or the next milestone if ~"priority::2". -->
/milestone % /milestone %

View file

@ -27,7 +27,7 @@ After your merge request has been approved according to our [approval guidelines
* At this point, it might be easy to squash the commits from the MR into one * At this point, it might be easy to squash the commits from the MR into one
* You can use the script `bin/secpick` instead of the following steps, to help you cherry-picking. See the [secpick documentation] * You can use the script `bin/secpick` instead of the following steps, to help you cherry-picking. See the [secpick documentation]
- [ ] Create each MR targeting the stable branch `X-Y-stable`, using the [Security Release merge request template]. - [ ] Create each MR targeting the stable branch `X-Y-stable`, using the [Security Release merge request template].
* Every merge request will have its own set of TODOs, so make sure to complete those. * Every merge request will have its own set of to-dos, so make sure to complete those.
- [ ] On the "Related merge requests" section, ensure that `4` merge requests are associated: The one targeting `master` and the `3` backports. - [ ] On the "Related merge requests" section, ensure that `4` merge requests are associated: The one targeting `master` and the `3` backports.
- [ ] If this issue requires less than `4` merge requests, post a message on the Security Release Tracking Issue and ping the Release Managers. - [ ] If this issue requires less than `4` merge requests, post a message on the Security Release Tracking Issue and ping the Release Managers.

View file

@ -12,7 +12,7 @@ Actionable insights always have a follow-up action that needs to take place as a
#### Description #### Description
- [ ] Provide some brief detials on the actionable insight and the action to take - [ ] Provide some brief details on the actionable insight and the action to take
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -28,4 +28,4 @@ Actionable insights always have a follow-up action that needs to take place as a
~"Actionable Insight" /label ~"Actionable Insight"

View file

@ -16,9 +16,10 @@
## Author's checklist (required) ## Author's checklist (required)
- [ ] Follow the [Documentation Guidelines](https://docs.gitlab.com/ee/development/documentation/) and [Style Guide](https://docs.gitlab.com/ee/development/documentation/styleguide.html). - [ ] Follow the [Documentation Guidelines](https://docs.gitlab.com/ee/development/documentation/) and [Style Guide](https://docs.gitlab.com/ee/development/documentation/styleguide.html).
- If you have `developer` access or higher (for example, GitLab team members or [Core Team](https://about.gitlab.com/community/core-team/) members) - If you have **Developer** permissions or higher:
- [ ] Ensure that the [product tier badge](https://docs.gitlab.com/ee/development/documentation/styleguide.html#product-badges) is added to doc's `h1`.
- [ ] Apply the ~documentation label, plus: - [ ] Apply the ~documentation label, plus:
- The corresponding DevOps stage and group label, if applicable. - The corresponding DevOps stage and group labels, if applicable.
- ~"development guidelines" when changing docs under `doc/development/*`, `CONTRIBUTING.md`, or `README.md`. - ~"development guidelines" when changing docs under `doc/development/*`, `CONTRIBUTING.md`, or `README.md`.
- ~"development guidelines" and ~"Documentation guidelines" when changing docs under `development/documentation/*`. - ~"development guidelines" and ~"Documentation guidelines" when changing docs under `development/documentation/*`.
- ~"development guidelines" and ~"Description templates (.gitlab/\*)" when creating/updating issue and MR description templates. - ~"development guidelines" and ~"Description templates (.gitlab/\*)" when creating/updating issue and MR description templates.
@ -30,10 +31,9 @@ When applicable:
- [ ] Update the [permissions table](https://docs.gitlab.com/ee/user/permissions.html). - [ ] Update the [permissions table](https://docs.gitlab.com/ee/user/permissions.html).
- [ ] Link docs to and from the higher-level index page, plus other related docs where helpful. - [ ] Link docs to and from the higher-level index page, plus other related docs where helpful.
- [ ] Add the [product tier badge](https://docs.gitlab.com/ee/development/documentation/styleguide.html#product-badges) accordingly.
- [ ] Add [GitLab's version history note(s)](https://docs.gitlab.com/ee/development/documentation/styleguide.html#text-for-documentation-requiring-version-text). - [ ] Add [GitLab's version history note(s)](https://docs.gitlab.com/ee/development/documentation/styleguide.html#text-for-documentation-requiring-version-text).
- [ ] Add the [product tier badge](https://docs.gitlab.com/ee/development/documentation/styleguide.html#product-badges).
- [ ] Add/update the [feature flag section](https://docs.gitlab.com/ee/development/documentation/feature_flags.html). - [ ] Add/update the [feature flag section](https://docs.gitlab.com/ee/development/documentation/feature_flags.html).
- [ ] If you're changing document headings, search `doc/*`, `app/views/*`, and `ee/app/views/*` for old headings replacing with the new ones to [avoid broken anchors](https://docs.gitlab.com/ee/development/documentation/styleguide.html#anchor-links).
## Review checklist ## Review checklist
@ -46,8 +46,9 @@ All reviewers can help ensure accuracy, clarity, completeness, and adherence to
**2. Technical Writer** **2. Technical Writer**
- [ ] Technical writer review. If not requested for this MR, must be scheduled post-merge. To request for this MR, assign the writer listed for the applicable [DevOps stage](https://about.gitlab.com/handbook/product/product-categories/#devops-stages). - [ ] Technical writer review. If not requested for this MR, must be scheduled post-merge. To request for this MR, assign the writer listed for the applicable [DevOps stage](https://about.gitlab.com/handbook/product/product-categories/#devops-stages).
- [ ] Ensure ~"Technical Writing", ~"documentation", and a `docs::` scoped label are added. - [ ] Ensure docs metadata are present and up-to-date.
- [ ] Add ~docs-only when the only files changed are under `doc/*`. - [ ] Ensure ~"Technical Writing" and ~"documentation" are added.
- [ ] Add the corresponding `docs::` scoped label.
- [ ] Add ~"tw::doing" when starting work on the MR. - [ ] Add ~"tw::doing" when starting work on the MR.
- [ ] Add ~"tw::finished" if Technical Writing team work on the MR is complete but it remains open. - [ ] Add ~"tw::finished" if Technical Writing team work on the MR is complete but it remains open.

View file

@ -23,7 +23,6 @@ See [the general developer security release guidelines](https://gitlab.com/gitla
- [ ] Ensure it's approved by an AppSec engineer. - [ ] Ensure it's approved by an AppSec engineer.
- If you're unsure who should approve, find the AppSec engineer associated to the issue in the [Canonical repository], or ask #sec-appsec on Slack. - If you're unsure who should approve, find the AppSec engineer associated to the issue in the [Canonical repository], or ask #sec-appsec on Slack.
- Trigger the [`package-and-qa` build]. The docker image generated will be used by the AppSec engineer to validate the security vulnerability has been remediated. - Trigger the [`package-and-qa` build]. The docker image generated will be used by the AppSec engineer to validate the security vulnerability has been remediated.
- [ ] Merge request _must_ close the corresponding security issue.
- [ ] For a backport MR targeting a versioned stable branch (`X-Y-stable-ee`) - [ ] For a backport MR targeting a versioned stable branch (`X-Y-stable-ee`)
- [ ] Ensure it's approved by a maintainer. - [ ] Ensure it's approved by a maintainer.

View file

@ -63,6 +63,8 @@ linters:
- "app/views/admin/users/new.html.haml" - "app/views/admin/users/new.html.haml"
- "app/views/admin/users/projects.html.haml" - "app/views/admin/users/projects.html.haml"
- "app/views/admin/users/show.html.haml" - "app/views/admin/users/show.html.haml"
- 'app/views/authentication/_authenticate.html.haml'
- 'app/views/authentication/_register.html.haml'
- "app/views/clusters/clusters/_cluster.html.haml" - "app/views/clusters/clusters/_cluster.html.haml"
- "app/views/clusters/clusters/new.html.haml" - "app/views/clusters/clusters/new.html.haml"
- "app/views/dashboard/milestones/index.html.haml" - "app/views/dashboard/milestones/index.html.haml"
@ -116,9 +118,12 @@ linters:
- "app/views/import/bitbucket/status.html.haml" - "app/views/import/bitbucket/status.html.haml"
- "app/views/import/bitbucket_server/status.html.haml" - "app/views/import/bitbucket_server/status.html.haml"
- "app/views/invites/show.html.haml" - "app/views/invites/show.html.haml"
- "app/views/jira_connect/subscriptions/index.html.haml"
- "app/views/layouts/_mailer.html.haml" - "app/views/layouts/_mailer.html.haml"
- "app/views/layouts/experiment_mailer.html.haml"
- "app/views/layouts/header/_default.html.haml" - "app/views/layouts/header/_default.html.haml"
- "app/views/layouts/header/_new_dropdown.haml" - "app/views/layouts/header/_new_dropdown.haml"
- "app/views/layouts/jira_connect.html.haml"
- "app/views/layouts/notify.html.haml" - "app/views/layouts/notify.html.haml"
- "app/views/notify/_failed_builds.html.haml" - "app/views/notify/_failed_builds.html.haml"
- "app/views/notify/_reassigned_issuable_email.html.haml" - "app/views/notify/_reassigned_issuable_email.html.haml"
@ -289,7 +294,6 @@ linters:
- "app/views/shared/issuable/_search_bar.html.haml" - "app/views/shared/issuable/_search_bar.html.haml"
- "app/views/shared/issuable/_sidebar.html.haml" - "app/views/shared/issuable/_sidebar.html.haml"
- "app/views/shared/issuable/form/_default_templates.html.haml" - "app/views/shared/issuable/form/_default_templates.html.haml"
- "app/views/shared/issuable/form/_issue_assignee.html.haml"
- "app/views/shared/issuable/form/_template_selector.html.haml" - "app/views/shared/issuable/form/_template_selector.html.haml"
- "app/views/shared/issuable/form/_title.html.haml" - "app/views/shared/issuable/form/_title.html.haml"
- "app/views/shared/labels/_form.html.haml" - "app/views/shared/labels/_form.html.haml"
@ -309,8 +313,6 @@ linters:
- "app/views/shared/web_hooks/_form.html.haml" - "app/views/shared/web_hooks/_form.html.haml"
- "app/views/shared/web_hooks/_hook.html.haml" - "app/views/shared/web_hooks/_hook.html.haml"
- "app/views/shared/wikis/_pages_wiki_page.html.haml" - "app/views/shared/wikis/_pages_wiki_page.html.haml"
- "app/views/u2f/_authenticate.html.haml"
- "app/views/u2f/_register.html.haml"
- "app/views/users/_deletion_guidance.html.haml" - "app/views/users/_deletion_guidance.html.haml"
- "ee/app/views/admin/_namespace_plan_info.html.haml" - "ee/app/views/admin/_namespace_plan_info.html.haml"
- "ee/app/views/admin/application_settings/_templates.html.haml" - "ee/app/views/admin/application_settings/_templates.html.haml"
@ -333,8 +335,6 @@ linters:
- "ee/app/views/groups/group_members/_sync_button.html.haml" - "ee/app/views/groups/group_members/_sync_button.html.haml"
- "ee/app/views/groups/hooks/edit.html.haml" - "ee/app/views/groups/hooks/edit.html.haml"
- "ee/app/views/groups/ldap_group_links/index.html.haml" - "ee/app/views/groups/ldap_group_links/index.html.haml"
- "ee/app/views/jira_connect/subscriptions/index.html.haml"
- "ee/app/views/layouts/jira_connect.html.haml"
- "ee/app/views/layouts/nav/ee/admin/_new_monitoring_sidebar.html.haml" - "ee/app/views/layouts/nav/ee/admin/_new_monitoring_sidebar.html.haml"
- "ee/app/views/layouts/service_desk.html.haml" - "ee/app/views/layouts/service_desk.html.haml"
- "ee/app/views/ldap_group_links/_form.html.haml" - "ee/app/views/ldap_group_links/_form.html.haml"

View file

@ -45,9 +45,11 @@
"Debian", "Debian",
"DevOps", "DevOps",
"Docker", "Docker",
"DockerSlim",
"Elasticsearch", "Elasticsearch",
"Facebook", "Facebook",
"fastlane", "fastlane",
"fluent-plugin-redis-slowlog",
"GDK", "GDK",
"Geo", "Geo",
"Git LFS", "Git LFS",
@ -71,6 +73,7 @@
"Gzip", "Gzip",
"Helm", "Helm",
"HipChat", "HipChat",
"ID",
"Ingress", "Ingress",
"jasmine-jquery", "jasmine-jquery",
"JavaScript", "JavaScript",

View file

@ -1,49 +0,0 @@
user: git
group: git
services:
- postgres
before_precompile: ./bin/pkgr_before_precompile.sh
env:
- SKIP_STORAGE_VALIDATION=true
targets:
debian-7: &wheezy
build_dependencies:
- libkrb5-dev
- libicu-dev
- cmake
- pkg-config
dependencies:
- libicu48
- libpcre3
- git
ubuntu-12.04: *wheezy
ubuntu-14.04:
build_dependencies:
- libkrb5-dev
- libicu-dev
- cmake
- pkg-config
dependencies:
- libicu52
- libpcre3
- git
ubuntu-16.04:
build_dependencies:
- libkrb5-dev
- libicu-dev
- cmake
- pkg-config
dependencies:
- libicu55
- libpcre3
- git
centos-6:
build_dependencies:
- krb5-devel
- libicu-devel
- cmake
- pkgconfig
dependencies:
- libicu
- pcre
- git

View file

@ -60,6 +60,9 @@ Style/MutableConstant:
Style/SafeNavigation: Style/SafeNavigation:
Enabled: false Enabled: false
Style/AccessModifierDeclarations:
AllowModifiersOnSymbols: true
# Frozen String Literal # Frozen String Literal
Style/FrozenStringLiteralComment: Style/FrozenStringLiteralComment:
Enabled: true Enabled: true
@ -243,6 +246,13 @@ Gitlab/Json:
- 'lib/quality/**/*' - 'lib/quality/**/*'
- 'lib/gitlab/danger/**/*' - 'lib/gitlab/danger/**/*'
Gitlab/AvoidUploadedFileFromParams:
Enabled: true
Exclude:
- 'lib/gitlab/middleware/multipart.rb'
- 'spec/**/*'
- 'ee/spec/**/*'
GitlabSecurity/PublicSend: GitlabSecurity/PublicSend:
Enabled: true Enabled: true
Exclude: Exclude:
@ -282,6 +292,14 @@ Cop/ActiveRecordAssociationReload:
Gitlab/AvoidFeatureGet: Gitlab/AvoidFeatureGet:
Enabled: true Enabled: true
RSpec/TimecopFreeze:
Enabled: false
AutoCorrect: true
Include:
- 'spec/**/*.rb'
- 'ee/spec/**/*.rb'
- 'qa/spec/**/*.rb'
Naming/PredicateName: Naming/PredicateName:
Enabled: true Enabled: true
Exclude: Exclude:
@ -509,3 +527,24 @@ Cop/PutGroupRoutesUnderScope:
Include: Include:
- 'config/routes/group.rb' - 'config/routes/group.rb'
- 'ee/config/routes/group.rb' - 'ee/config/routes/group.rb'
Migration/ComplexIndexesRequireName:
Exclude:
- !ruby/regexp /\Adb\/(post_)?migrate\/201.*\.rb\z/
- !ruby/regexp /\Adb\/(post_)?migrate\/20200[1-7].*\.rb\z/
Migration/ReferToIndexByName:
Exclude:
- !ruby/regexp /\Adb\/(post_)?migrate\/201.*\.rb\z/
- !ruby/regexp /\Adb\/(post_)?migrate\/20200[1-7].*\.rb\z/
- !ruby/regexp /\Aee\/db\/geo\/(post_)?migrate\/201.*\.rb\z/
Migration/CreateTableWithForeignKeys:
# Disable this cop for all the existing migrations
Exclude:
- !ruby/regexp /\Adb\/(?:post_)?migrate\/(?:201[0-9]\d+|20200[0-8][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])_.+\.rb\z/
Gitlab/RailsLogger:
Exclude:
- 'spec/**/*.rb'
- 'ee/spec/**/*.rb'

View file

@ -18,44 +18,6 @@ Capybara/CurrentPathExpectation:
Layout/ArgumentAlignment: Layout/ArgumentAlignment:
Enabled: false Enabled: false
# Offense count: 13
# Cop supports --auto-correct.
Layout/ClosingHeredocIndentation:
Exclude:
- 'app/graphql/mutations/merge_requests/set_wip.rb'
- 'ee/db/geo/migrate/20180322062741_migrate_ci_job_artifacts_to_separate_registry.rb'
- 'ee/lib/gitlab/geo/health_check.rb'
- 'spec/features/merge_request/user_sees_diff_spec.rb'
- 'spec/lib/gitlab/asciidoc_spec.rb'
- 'spec/lib/gitlab/checks/project_moved_spec.rb'
- 'spec/rubocop/cop/active_record_association_reload_spec.rb'
- 'spec/services/task_list_toggle_service_spec.rb'
# Offense count: 13
# Cop supports --auto-correct.
Layout/ClosingParenthesisIndentation:
Exclude:
- 'db/post_migrate/20180704145007_update_project_indexes.rb'
- 'ee/db/geo/migrate/20180405074130_add_partial_index_project_repository_verification.rb'
- 'spec/services/issues/resolve_discussions_spec.rb'
- 'spec/services/projects/update_service_spec.rb'
- 'spec/support/helpers/stub_object_storage.rb'
- 'spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb'
# Offense count: 72
# Cop supports --auto-correct.
Layout/EmptyLinesAroundArguments:
Exclude:
- 'app/models/concerns/discussion_on_diff.rb'
- 'app/models/concerns/resolvable_discussion.rb'
- 'app/models/diff_discussion.rb'
- 'app/models/discussion.rb'
- 'ee/spec/models/geo/project_registry_spec.rb'
- 'lib/banzai/pipeline/broadcast_message_pipeline.rb'
- 'lib/banzai/pipeline/gfm_pipeline.rb'
- 'lib/banzai/pipeline/single_line_pipeline.rb'
- 'spec/features/markdown/copy_as_gfm_spec.rb'
# Offense count: 413 # Offense count: 413
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth. # Configuration parameters: EnforcedStyle, IndentationWidth.
@ -70,17 +32,6 @@ Layout/FirstArrayElementIndentation:
Layout/FirstHashElementIndentation: Layout/FirstHashElementIndentation:
Enabled: false Enabled: false
# Offense count: 4
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: consistent, align_parentheses
Layout/FirstParameterIndentation:
Exclude:
- 'lib/gitlab/cross_project_access.rb'
- 'lib/gitlab/data_builder/push.rb'
- 'spec/support/helpers/repo_helpers.rb'
- 'spec/support/helpers/stub_object_storage.rb'
# Offense count: 2164 # Offense count: 2164
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
@ -104,33 +55,11 @@ Layout/LineLength:
Layout/MultilineOperationIndentation: Layout/MultilineOperationIndentation:
Enabled: false Enabled: false
# Offense count: 9
# Cop supports --auto-correct.
Layout/RescueEnsureAlignment:
Exclude:
- 'app/models/blob_viewer/dependency_manager.rb'
- 'app/models/project.rb'
- 'app/services/prometheus/proxy_service.rb'
- 'app/workers/delete_stored_files_worker.rb'
- 'config/initializers/1_settings.rb'
- 'config/initializers/trusted_proxies.rb'
- 'lib/gitlab/background_migration/archive_legacy_traces.rb'
- 'lib/gitlab/highlight.rb'
- 'lib/tasks/gitlab/lfs/migrate.rake'
# Offense count: 36 # Offense count: 36
# Cop supports --auto-correct. # Cop supports --auto-correct.
Layout/SpaceAroundMethodCallOperator: Layout/SpaceAroundMethodCallOperator:
Enabled: false Enabled: false
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: AllowForAlignment.
Layout/SpaceBeforeFirstArg:
Exclude:
- 'spec/requests/api/runner_spec.rb'
- 'spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb'
# Offense count: 642 # Offense count: 642
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle. # Configuration parameters: EnforcedStyle.
@ -158,23 +87,6 @@ Layout/SpaceInsideParens:
Lint/MissingCopEnableDirective: Lint/MissingCopEnableDirective:
Enabled: false Enabled: false
# Offense count: 11
# Cop supports --auto-correct.
Lint/NonDeterministicRequireOrder:
Exclude:
- 'ee/spec/spec_helper.rb'
- 'qa/spec/spec_helper.rb'
- 'spec/spec_helper.rb'
# Offense count: 3
# Configuration parameters: AllowedImplicitNamespaces.
# AllowedImplicitNamespaces: Gem
Lint/RaiseException:
Exclude:
- 'db/migrate/20190402150158_backport_enterprise_schema.rb'
- 'ee/spec/requests/api/helpers_spec.rb'
- 'spec/requests/api/helpers_spec.rb'
# Offense count: 27 # Offense count: 27
# Cop supports --auto-correct. # Cop supports --auto-correct.
Lint/RedundantCopDisableDirective: Lint/RedundantCopDisableDirective:
@ -201,14 +113,6 @@ Lint/UriEscapeUnescape:
- 'spec/lib/google_api/auth_spec.rb' - 'spec/lib/google_api/auth_spec.rb'
- 'spec/requests/api/files_spec.rb' - 'spec/requests/api/files_spec.rb'
# Offense count: 3
# Cop supports --auto-correct.
Lint/UriRegexp:
Exclude:
- 'app/models/concerns/mentionable/reference_regexes.rb'
- 'app/services/projects/download_service.rb'
- 'lib/gitlab/ci/pipeline/chain/config/content/remote.rb'
# Offense count: 65 # Offense count: 65
# Cop supports --auto-correct. # Cop supports --auto-correct.
Migration/DepartmentName: Migration/DepartmentName:
@ -295,30 +199,6 @@ RSpec/ExpectChange:
RSpec/ExpectInHook: RSpec/ExpectInHook:
Enabled: false Enabled: false
# Offense count: 9
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: it_behaves_like, it_should_behave_like
RSpec/ItBehavesLike:
Exclude:
- 'spec/lib/gitlab/git/commit_spec.rb'
- 'spec/services/notification_service_spec.rb'
# Offense count: 68
# Cop supports --auto-correct.
RSpec/LetBeforeExamples:
Exclude:
- 'spec/lib/banzai/filter/issue_reference_filter_spec.rb'
- 'spec/lib/banzai/filter/user_reference_filter_spec.rb'
- 'spec/lib/gitlab/email/handler/create_issue_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
- 'spec/models/commit_range_spec.rb'
- 'spec/models/milestone_spec.rb'
- 'spec/models/project_services/packagist_service_spec.rb'
- 'spec/rubocop/cop/migration/update_column_in_batches_spec.rb'
- 'spec/serializers/pipeline_details_entity_spec.rb'
# Offense count: 2188 # Offense count: 2188
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: Strict, EnforcedStyle, AllowedExplicitMatchers. # Configuration parameters: Strict, EnforcedStyle, AllowedExplicitMatchers.
@ -618,17 +498,6 @@ Security/YAMLLoad:
- 'spec/initializers/secret_token_spec.rb' - 'spec/initializers/secret_token_spec.rb'
- 'spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb' - 'spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb'
# Offense count: 10
# Configuration parameters: EnforcedStyle, AllowModifiersOnSymbols.
# SupportedStyles: inline, group
Style/AccessModifierDeclarations:
Exclude:
- 'app/helpers/issues_helper.rb'
- 'app/helpers/lazy_image_tag_helper.rb'
- 'lib/gitlab/cache/request_cache.rb'
- 'lib/gitlab/request_profiler.rb'
- 'spec/support/forgery_protection.rb'
# Offense count: 148 # Offense count: 148
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle. # Configuration parameters: EnforcedStyle.
@ -636,12 +505,6 @@ Style/AccessModifierDeclarations:
Style/BarePercentLiterals: Style/BarePercentLiterals:
Enabled: false Enabled: false
# Offense count: 5
Style/CommentedKeyword:
Exclude:
- 'lib/tasks/gitlab/backup.rake'
- 'spec/tasks/gitlab/backup_rake_spec.rb'
# Offense count: 5 # Offense count: 5
# Cop supports --auto-correct. # Cop supports --auto-correct.
Style/EachWithObject: Style/EachWithObject:
@ -659,24 +522,6 @@ Style/EachWithObject:
Style/EmptyElse: Style/EmptyElse:
Enabled: false Enabled: false
# Offense count: 11
# Cop supports --auto-correct.
Style/EmptyLambdaParameter:
Exclude:
- 'app/models/ci/build.rb'
- 'app/models/ci/runner.rb'
# Offense count: 7
# Cop supports --auto-correct.
Style/EmptyLiteral:
Exclude:
- 'lib/gitlab/fogbugz_import/importer.rb'
- 'lib/gitlab/git/diff_collection.rb'
- 'lib/gitlab/gitaly_client.rb'
- 'spec/helpers/merge_requests_helper_spec.rb'
- 'spec/lib/gitlab/workhorse_spec.rb'
- 'spec/requests/api/jobs_spec.rb'
# Offense count: 170 # Offense count: 170
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle. # Configuration parameters: EnforcedStyle.
@ -735,13 +580,6 @@ Style/MixinUsage:
- 'spec/factories/notes.rb' - 'spec/factories/notes.rb'
- 'spec/lib/gitlab/import_export/version_checker_spec.rb' - 'spec/lib/gitlab/import_export/version_checker_spec.rb'
# Offense count: 2
# Cop supports --auto-correct.
Style/MultilineIfModifier:
Exclude:
- 'app/services/ci/process_pipeline_service.rb'
- 'lib/api/commit_statuses.rb'
# Offense count: 29 # Offense count: 29
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, MinBodyLength. # Configuration parameters: EnforcedStyle, MinBodyLength.
@ -767,22 +605,6 @@ Style/ParallelAssignment:
Style/PercentLiteralDelimiters: Style/PercentLiteralDelimiters:
Enabled: false Enabled: false
# Offense count: 15
# Cop supports --auto-correct.
Style/PerlBackrefs:
Exclude:
- 'app/controllers/projects/application_controller.rb'
- 'app/helpers/submodule_helper.rb'
- 'lib/backup/manager.rb'
- 'lib/banzai/filter/abstract_reference_filter.rb'
- 'lib/banzai/filter/autolink_filter.rb'
- 'lib/banzai/filter/emoji_filter.rb'
- 'lib/banzai/filter/gollum_tags_filter.rb'
- 'lib/expand_variables.rb'
- 'lib/gitlab/diff/highlight.rb'
- 'lib/gitlab/search_results.rb'
- 'lib/gitlab/sherlock/query.rb'
# Offense count: 200 # Offense count: 200
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle. # Configuration parameters: EnforcedStyle.
@ -805,13 +627,6 @@ Style/RedundantInterpolation:
Style/RedundantSelf: Style/RedundantSelf:
Enabled: false Enabled: false
# Offense count: 2
# Cop supports --auto-correct.
Style/RedundantSort:
Exclude:
- 'app/presenters/packages/nuget/search_results_presenter.rb'
- 'spec/presenters/packages/nuget/search_results_presenter_spec.rb'
# Offense count: 120 # Offense count: 120
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, AllowInnerSlashes. # Configuration parameters: EnforcedStyle, AllowInnerSlashes.
@ -831,21 +646,6 @@ Style/RescueModifier:
Style/RescueStandardError: Style/RescueStandardError:
Enabled: false Enabled: false
# Offense count: 4
# Cop supports --auto-correct.
Style/SelfAssignment:
Exclude:
- 'app/models/concerns/bulk_member_access_load.rb'
- 'app/serializers/base_serializer.rb'
- 'spec/support/import_export/configuration_helper.rb'
# Offense count: 50
# Cop supports --auto-correct.
# Configuration parameters: AllowIfMethodIsEmpty.
Style/SingleLineMethods:
Exclude:
- 'lib/gitlab/ci/ansi2html.rb'
# Offense count: 102 # Offense count: 102
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: . # Configuration parameters: .
@ -879,11 +679,6 @@ Rails/SaveBang:
- 'ee/spec/initializers/fog_google_https_private_urls_spec.rb' - 'ee/spec/initializers/fog_google_https_private_urls_spec.rb'
- 'ee/spec/lib/analytics/merge_request_metrics_calculator_spec.rb' - 'ee/spec/lib/analytics/merge_request_metrics_calculator_spec.rb'
- 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb' - 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules_spec.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/move_epic_issues_after_epics_spec.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/populate_any_approval_rule_for_merge_requests_spec.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/populate_any_approval_rule_for_projects_spec.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/prune_orphaned_geo_events_spec.rb'
- 'ee/spec/lib/ee/gitlab/checks/push_rules/commit_check_spec.rb' - 'ee/spec/lib/ee/gitlab/checks/push_rules/commit_check_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/pipeline/quota/activity_spec.rb' - 'ee/spec/lib/ee/gitlab/ci/pipeline/quota/activity_spec.rb'
- 'ee/spec/lib/gitlab/auth/ldap/access_spec.rb' - 'ee/spec/lib/gitlab/auth/ldap/access_spec.rb'
@ -892,9 +687,6 @@ Rails/SaveBang:
- 'ee/spec/lib/gitlab/background_migration/fix_orphan_promoted_issues_spec.rb' - 'ee/spec/lib/gitlab/background_migration/fix_orphan_promoted_issues_spec.rb'
- 'ee/spec/lib/gitlab/elastic/search_results_spec.rb' - 'ee/spec/lib/gitlab/elastic/search_results_spec.rb'
- 'ee/spec/lib/gitlab/email/handler/ee/service_desk_handler_spec.rb' - 'ee/spec/lib/gitlab/email/handler/ee/service_desk_handler_spec.rb'
- 'ee/spec/lib/gitlab/geo/cron_manager_spec.rb'
- 'ee/spec/lib/gitlab/geo/jwt_request_decoder_spec.rb'
- 'ee/spec/lib/gitlab/geo/oauth/session_spec.rb'
- 'ee/spec/lib/gitlab/geo_spec.rb' - 'ee/spec/lib/gitlab/geo_spec.rb'
- 'ee/spec/lib/gitlab/git_access_spec.rb' - 'ee/spec/lib/gitlab/git_access_spec.rb'
- 'ee/spec/lib/gitlab/import_export/group/relation_factory_spec.rb' - 'ee/spec/lib/gitlab/import_export/group/relation_factory_spec.rb'
@ -910,7 +702,6 @@ Rails/SaveBang:
- 'ee/spec/models/approval_project_rule_spec.rb' - 'ee/spec/models/approval_project_rule_spec.rb'
- 'ee/spec/models/approval_state_spec.rb' - 'ee/spec/models/approval_state_spec.rb'
- 'ee/spec/models/burndown_spec.rb' - 'ee/spec/models/burndown_spec.rb'
- 'ee/spec/models/ci/build_spec.rb'
- 'ee/spec/models/ci/pipeline_spec.rb' - 'ee/spec/models/ci/pipeline_spec.rb'
- 'ee/spec/models/ci/subscriptions/project_spec.rb' - 'ee/spec/models/ci/subscriptions/project_spec.rb'
- 'ee/spec/models/concerns/approver_migrate_hook_spec.rb' - 'ee/spec/models/concerns/approver_migrate_hook_spec.rb'
@ -935,14 +726,8 @@ Rails/SaveBang:
- 'ee/spec/models/license_spec.rb' - 'ee/spec/models/license_spec.rb'
- 'ee/spec/models/merge_request_spec.rb' - 'ee/spec/models/merge_request_spec.rb'
- 'ee/spec/models/merge_train_spec.rb' - 'ee/spec/models/merge_train_spec.rb'
- 'ee/spec/models/operations/feature_flag_scope_spec.rb'
- 'ee/spec/models/operations/feature_flag_spec.rb'
- 'ee/spec/models/operations/feature_flags/strategy_spec.rb'
- 'ee/spec/models/operations/feature_flags/user_list_spec.rb'
- 'spec/models/packages/package_spec.rb' - 'spec/models/packages/package_spec.rb'
- 'ee/spec/models/project_ci_cd_setting_spec.rb' - 'ee/spec/models/project_ci_cd_setting_spec.rb'
- 'ee/spec/models/project_services/github_service_spec.rb'
- 'ee/spec/models/project_services/jenkins_service_spec.rb'
- 'ee/spec/models/project_spec.rb' - 'ee/spec/models/project_spec.rb'
- 'ee/spec/models/protected_environment_spec.rb' - 'ee/spec/models/protected_environment_spec.rb'
- 'ee/spec/models/repository_spec.rb' - 'ee/spec/models/repository_spec.rb'
@ -978,9 +763,6 @@ Rails/SaveBang:
- 'ee/spec/requests/lfs_http_spec.rb' - 'ee/spec/requests/lfs_http_spec.rb'
- 'ee/spec/services/approval_rules/finalize_service_spec.rb' - 'ee/spec/services/approval_rules/finalize_service_spec.rb'
- 'ee/spec/services/approval_rules/update_service_spec.rb' - 'ee/spec/services/approval_rules/update_service_spec.rb'
- 'ee/spec/services/ci/minutes/email_notification_service_spec.rb'
- 'ee/spec/services/ci/process_build_service_spec.rb'
- 'ee/spec/services/ci/register_job_service_spec.rb'
- 'ee/spec/services/ee/boards/issues/create_service_spec.rb' - 'ee/spec/services/ee/boards/issues/create_service_spec.rb'
- 'ee/spec/services/ee/boards/issues/list_service_spec.rb' - 'ee/spec/services/ee/boards/issues/list_service_spec.rb'
- 'ee/spec/services/ee/boards/lists/list_service_spec.rb' - 'ee/spec/services/ee/boards/lists/list_service_spec.rb'
@ -991,7 +773,6 @@ Rails/SaveBang:
- 'ee/spec/services/ee/merge_requests/update_service_spec.rb' - 'ee/spec/services/ee/merge_requests/update_service_spec.rb'
- 'ee/spec/services/ee/notes/quick_actions_service_spec.rb' - 'ee/spec/services/ee/notes/quick_actions_service_spec.rb'
- 'ee/spec/services/ee/notification_service_spec.rb' - 'ee/spec/services/ee/notification_service_spec.rb'
- 'ee/spec/services/ee/resource_events/change_weight_service_spec.rb'
- 'ee/spec/services/epic_links/create_service_spec.rb' - 'ee/spec/services/epic_links/create_service_spec.rb'
- 'ee/spec/services/epics/close_service_spec.rb' - 'ee/spec/services/epics/close_service_spec.rb'
- 'ee/spec/services/epics/issue_promote_service_spec.rb' - 'ee/spec/services/epics/issue_promote_service_spec.rb'
@ -1007,14 +788,7 @@ Rails/SaveBang:
- 'ee/spec/services/groups/autocomplete_service_spec.rb' - 'ee/spec/services/groups/autocomplete_service_spec.rb'
- 'ee/spec/services/ldap_group_reset_service_spec.rb' - 'ee/spec/services/ldap_group_reset_service_spec.rb'
- 'ee/spec/services/lfs/unlock_file_service_spec.rb' - 'ee/spec/services/lfs/unlock_file_service_spec.rb'
- 'ee/spec/services/merge_requests/approval_service_spec.rb'
- 'ee/spec/services/merge_requests/remove_approval_service_spec.rb'
- 'ee/spec/services/merge_requests/update_blocks_service_spec.rb'
- 'ee/spec/services/merge_trains/refresh_merge_request_service_spec.rb' - 'ee/spec/services/merge_trains/refresh_merge_request_service_spec.rb'
- 'ee/spec/services/projects/after_rename_service_spec.rb'
- 'ee/spec/services/projects/import_export/export_service_spec.rb'
- 'ee/spec/services/projects/update_mirror_service_spec.rb'
- 'ee/spec/services/projects/update_service_spec.rb'
- 'ee/spec/services/quick_actions/interpret_service_spec.rb' - 'ee/spec/services/quick_actions/interpret_service_spec.rb'
- 'ee/spec/services/slash_commands/global_slack_handler_spec.rb' - 'ee/spec/services/slash_commands/global_slack_handler_spec.rb'
- 'ee/spec/services/start_pull_mirroring_service_spec.rb' - 'ee/spec/services/start_pull_mirroring_service_spec.rb'
@ -1027,16 +801,7 @@ Rails/SaveBang:
- 'ee/spec/support/shared_examples/finders/geo/framework_registry_finder_shared_examples.rb' - 'ee/spec/support/shared_examples/finders/geo/framework_registry_finder_shared_examples.rb'
- 'ee/spec/support/shared_examples/graphql/geo/geo_registries_resolver_shared_examples.rb' - 'ee/spec/support/shared_examples/graphql/geo/geo_registries_resolver_shared_examples.rb'
- 'ee/spec/support/shared_examples/lib/analytics/common_merge_request_metrics_refresh_shared_examples.rb' - 'ee/spec/support/shared_examples/lib/analytics/common_merge_request_metrics_refresh_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/concerns/replicator_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/elasticsearch_indexed_container_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/geo_framework_registry_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/member_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/mentionable_shared_examples.rb'
- 'ee/spec/support/shared_examples/policies/protected_environments_shared_examples.rb' - 'ee/spec/support/shared_examples/policies/protected_environments_shared_examples.rb'
- 'ee/spec/support/shared_examples/requests/api/graphql/geo/registries_shared_examples.rb'
- 'ee/spec/support/shared_examples/requests/api/project_approval_rules_api_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/build_execute_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/issue_epic_shared_examples.rb'
- 'ee/spec/workers/adjourned_project_deletion_worker_spec.rb' - 'ee/spec/workers/adjourned_project_deletion_worker_spec.rb'
- 'ee/spec/workers/clear_shared_runners_minutes_worker_spec.rb' - 'ee/spec/workers/clear_shared_runners_minutes_worker_spec.rb'
- 'ee/spec/workers/create_github_webhook_worker_spec.rb' - 'ee/spec/workers/create_github_webhook_worker_spec.rb'
@ -1049,6 +814,7 @@ Rails/SaveBang:
- 'ee/spec/workers/repository_import_worker_spec.rb' - 'ee/spec/workers/repository_import_worker_spec.rb'
- 'ee/spec/workers/update_all_mirrors_worker_spec.rb' - 'ee/spec/workers/update_all_mirrors_worker_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb' - 'qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_http_spec.rb' - 'qa/qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_http_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_ssh_with_key_spec.rb' - 'qa/qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_ssh_with_key_spec.rb'
- 'spec/controllers/abuse_reports_controller_spec.rb' - 'spec/controllers/abuse_reports_controller_spec.rb'
@ -1273,14 +1039,6 @@ Rails/SaveBang:
- 'spec/models/appearance_spec.rb' - 'spec/models/appearance_spec.rb'
- 'spec/models/application_record_spec.rb' - 'spec/models/application_record_spec.rb'
- 'spec/models/application_setting_spec.rb' - 'spec/models/application_setting_spec.rb'
- 'spec/models/ci/build_metadata_spec.rb'
- 'spec/models/ci/build_spec.rb'
- 'spec/models/ci/build_trace_chunk_spec.rb'
- 'spec/models/ci/instance_variable_spec.rb'
- 'spec/models/ci/legacy_stage_spec.rb'
- 'spec/models/ci/persistent_ref_spec.rb'
- 'spec/models/ci/pipeline_spec.rb'
- 'spec/models/ci/runner_spec.rb'
- 'spec/models/clusters/applications/helm_spec.rb' - 'spec/models/clusters/applications/helm_spec.rb'
- 'spec/models/commit_spec.rb' - 'spec/models/commit_spec.rb'
- 'spec/models/commit_status_spec.rb' - 'spec/models/commit_status_spec.rb'
@ -1297,9 +1055,6 @@ Rails/SaveBang:
- 'spec/models/concerns/subscribable_spec.rb' - 'spec/models/concerns/subscribable_spec.rb'
- 'spec/models/concerns/token_authenticatable_spec.rb' - 'spec/models/concerns/token_authenticatable_spec.rb'
- 'spec/models/container_repository_spec.rb' - 'spec/models/container_repository_spec.rb'
- 'spec/models/cycle_analytics/issue_spec.rb'
- 'spec/models/cycle_analytics/plan_spec.rb'
- 'spec/models/cycle_analytics/production_spec.rb'
- 'spec/models/deploy_keys_project_spec.rb' - 'spec/models/deploy_keys_project_spec.rb'
- 'spec/models/deploy_token_spec.rb' - 'spec/models/deploy_token_spec.rb'
- 'spec/models/deployment_spec.rb' - 'spec/models/deployment_spec.rb'
@ -1329,15 +1084,13 @@ Rails/SaveBang:
- 'spec/models/namespace_spec.rb' - 'spec/models/namespace_spec.rb'
- 'spec/models/note_spec.rb' - 'spec/models/note_spec.rb'
- 'spec/models/notification_setting_spec.rb' - 'spec/models/notification_setting_spec.rb'
- 'spec/models/operations/feature_flag_scope_spec.rb'
- 'spec/models/operations/feature_flag_spec.rb'
- 'spec/models/operations/feature_flags/strategy_spec.rb'
- 'spec/models/operations/feature_flags/user_list_spec.rb'
- 'spec/models/pages_domain_spec.rb' - 'spec/models/pages_domain_spec.rb'
- 'spec/models/project_auto_devops_spec.rb' - 'spec/models/project_auto_devops_spec.rb'
- 'spec/models/project_feature_spec.rb' - 'spec/models/project_feature_spec.rb'
- 'spec/models/project_services/bamboo_service_spec.rb'
- 'spec/models/project_services/buildkite_service_spec.rb'
- 'spec/models/project_services/jira_service_spec.rb'
- 'spec/models/project_services/packagist_service_spec.rb'
- 'spec/models/project_services/pipelines_email_service_spec.rb'
- 'spec/models/project_services/teamcity_service_spec.rb'
- 'spec/models/project_spec.rb' - 'spec/models/project_spec.rb'
- 'spec/models/project_team_spec.rb' - 'spec/models/project_team_spec.rb'
- 'spec/models/protectable_dropdown_spec.rb' - 'spec/models/protectable_dropdown_spec.rb'
@ -1358,9 +1111,6 @@ Rails/SaveBang:
- 'spec/presenters/ci/build_runner_presenter_spec.rb' - 'spec/presenters/ci/build_runner_presenter_spec.rb'
- 'spec/presenters/ci/trigger_presenter_spec.rb' - 'spec/presenters/ci/trigger_presenter_spec.rb'
- 'spec/presenters/packages/conan/package_presenter_spec.rb' - 'spec/presenters/packages/conan/package_presenter_spec.rb'
- 'spec/requests/api/access_requests_spec.rb'
- 'spec/requests/api/boards_spec.rb'
- 'spec/requests/api/branches_spec.rb'
- 'spec/requests/api/ci/runner_spec.rb' - 'spec/requests/api/ci/runner_spec.rb'
- 'spec/requests/api/commit_statuses_spec.rb' - 'spec/requests/api/commit_statuses_spec.rb'
- 'spec/requests/api/conan_packages_spec.rb' - 'spec/requests/api/conan_packages_spec.rb'
@ -1377,36 +1127,11 @@ Rails/SaveBang:
- 'spec/requests/api/issues/post_projects_issues_spec.rb' - 'spec/requests/api/issues/post_projects_issues_spec.rb'
- 'spec/requests/api/jobs_spec.rb' - 'spec/requests/api/jobs_spec.rb'
- 'spec/requests/api/labels_spec.rb' - 'spec/requests/api/labels_spec.rb'
- 'spec/requests/api/maven_packages_spec.rb'
- 'spec/requests/api/members_spec.rb'
- 'spec/requests/api/merge_request_diffs_spec.rb'
- 'spec/requests/api/merge_requests_spec.rb'
- 'spec/requests/api/notes_spec.rb'
- 'spec/requests/api/pages/internal_access_spec.rb'
- 'spec/requests/api/pages/private_access_spec.rb'
- 'spec/requests/api/pages/public_access_spec.rb'
- 'spec/requests/api/pipeline_schedules_spec.rb'
- 'spec/requests/api/project_import_spec.rb' - 'spec/requests/api/project_import_spec.rb'
- 'spec/requests/api/project_milestones_spec.rb'
- 'spec/requests/api/projects_spec.rb'
- 'spec/requests/api/snippets_spec.rb'
- 'spec/requests/git_http_spec.rb'
- 'spec/requests/lfs_http_spec.rb'
- 'spec/requests/profiles/notifications_controller_spec.rb'
- 'spec/requests/projects/cycle_analytics_events_spec.rb' - 'spec/requests/projects/cycle_analytics_events_spec.rb'
- 'spec/serializers/environment_status_entity_spec.rb'
- 'spec/serializers/issue_entity_spec.rb'
- 'spec/serializers/job_entity_spec.rb'
- 'spec/serializers/merge_request_poll_widget_entity_spec.rb'
- 'spec/serializers/merge_request_widget_entity_spec.rb'
- 'spec/services/auth/container_registry_authentication_service_spec.rb' - 'spec/services/auth/container_registry_authentication_service_spec.rb'
- 'spec/services/auto_merge/base_service_spec.rb' - 'spec/services/auto_merge/base_service_spec.rb'
- 'spec/services/auto_merge_service_spec.rb' - 'spec/services/auto_merge_service_spec.rb'
- 'spec/services/ci/create_cross_project_pipeline_service_spec.rb'
- 'spec/services/ci/create_pipeline_service_spec.rb'
- 'spec/services/ci/register_job_service_spec.rb'
- 'spec/services/ci/retry_build_service_spec.rb'
- 'spec/services/ci/update_runner_service_spec.rb'
- 'spec/services/clusters/update_service_spec.rb' - 'spec/services/clusters/update_service_spec.rb'
- 'spec/services/deployments/after_create_service_spec.rb' - 'spec/services/deployments/after_create_service_spec.rb'
- 'spec/services/design_management/generate_image_versions_service_spec.rb' - 'spec/services/design_management/generate_image_versions_service_spec.rb'
@ -1418,20 +1143,7 @@ Rails/SaveBang:
- 'spec/services/issuable/bulk_update_service_spec.rb' - 'spec/services/issuable/bulk_update_service_spec.rb'
- 'spec/services/issuable/clone/attributes_rewriter_spec.rb' - 'spec/services/issuable/clone/attributes_rewriter_spec.rb'
- 'spec/services/issuable/common_system_notes_service_spec.rb' - 'spec/services/issuable/common_system_notes_service_spec.rb'
- 'spec/services/issues/close_service_spec.rb'
- 'spec/services/issues/create_service_spec.rb'
- 'spec/services/issues/export_csv_service_spec.rb'
- 'spec/services/issues/reopen_service_spec.rb'
- 'spec/services/issues/update_service_spec.rb'
- 'spec/services/labels/promote_service_spec.rb' - 'spec/services/labels/promote_service_spec.rb'
- 'spec/services/members/destroy_service_spec.rb'
- 'spec/services/merge_requests/build_service_spec.rb'
- 'spec/services/merge_requests/conflicts/list_service_spec.rb'
- 'spec/services/merge_requests/create_service_spec.rb'
- 'spec/services/merge_requests/merge_service_spec.rb'
- 'spec/services/merge_requests/post_merge_service_spec.rb'
- 'spec/services/merge_requests/refresh_service_spec.rb'
- 'spec/services/merge_requests/update_service_spec.rb'
- 'spec/services/milestones/destroy_service_spec.rb' - 'spec/services/milestones/destroy_service_spec.rb'
- 'spec/services/milestones/promote_service_spec.rb' - 'spec/services/milestones/promote_service_spec.rb'
- 'spec/services/milestones/transfer_service_spec.rb' - 'spec/services/milestones/transfer_service_spec.rb'
@ -1474,30 +1186,10 @@ Rails/SaveBang:
- 'spec/support/shared_examples/controllers/sessionless_auth_controller_shared_examples.rb' - 'spec/support/shared_examples/controllers/sessionless_auth_controller_shared_examples.rb'
- 'spec/support/shared_examples/features/editable_merge_request_shared_examples.rb' - 'spec/support/shared_examples/features/editable_merge_request_shared_examples.rb'
- 'spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb' - 'spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb'
- 'spec/support/shared_examples/models/chat_slash_commands_shared_examples.rb'
- 'spec/support/shared_examples/models/cluster_application_helm_cert_shared_examples.rb'
- 'spec/support/shared_examples/models/concerns/limitable_shared_examples.rb'
- 'spec/support/shared_examples/models/concerns/timebox_shared_examples.rb'
- 'spec/support/shared_examples/models/diff_note_after_commit_shared_examples.rb'
- 'spec/support/shared_examples/models/member_shared_examples.rb'
- 'spec/support/shared_examples/models/members_notifications_shared_example.rb'
- 'spec/support/shared_examples/models/mentionable_shared_examples.rb'
- 'spec/support/shared_examples/models/project_latest_successful_build_for_shared_examples.rb'
- 'spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb'
- 'spec/support/shared_examples/models/update_project_statistics_shared_examples.rb'
- 'spec/support/shared_examples/models/with_uploads_shared_examples.rb'
- 'spec/support/shared_examples/policies/project_policy_shared_examples.rb' - 'spec/support/shared_examples/policies/project_policy_shared_examples.rb'
- 'spec/support/shared_examples/quick_actions/issuable/issuable_quick_actions_shared_examples.rb' - 'spec/support/shared_examples/quick_actions/issuable/issuable_quick_actions_shared_examples.rb'
- 'spec/support/shared_examples/quick_actions/merge_request/merge_quick_action_shared_examples.rb' - 'spec/support/shared_examples/quick_actions/merge_request/merge_quick_action_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/award_emoji_todo_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/boards_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb'
- 'spec/support/shared_examples/serializers/note_entity_shared_examples.rb' - 'spec/support/shared_examples/serializers/note_entity_shared_examples.rb'
- 'spec/support/shared_examples/services/common_system_notes_shared_examples.rb'
- 'spec/support/shared_examples/services/issuable_shared_examples.rb'
- 'spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb'
- 'spec/tasks/gitlab/web_hook_rake_spec.rb' - 'spec/tasks/gitlab/web_hook_rake_spec.rb'
- 'spec/uploaders/file_uploader_spec.rb' - 'spec/uploaders/file_uploader_spec.rb'
- 'spec/uploaders/object_storage_spec.rb' - 'spec/uploaders/object_storage_spec.rb'

View file

@ -7,7 +7,7 @@ scss_files:
exclude: exclude:
- 'app/assets/stylesheets/pages/emojis.scss' - 'app/assets/stylesheets/pages/emojis.scss'
- 'app/assets/stylesheets/startup/startup-general.scss' - 'app/assets/stylesheets/startup/startup-*.scss'
linters: linters:
# Reports when you use improper spacing around ! (the "bang") in !default, # Reports when you use improper spacing around ! (the "bang") in !default,

14165
CHANGELOG.md

File diff suppressed because it is too large Load diff

View file

@ -1 +1 @@
13.3.9 13.4.6

View file

@ -1 +1 @@
2.6.0 2.7.0

1
GITLAB_KAS_VERSION Normal file
View file

@ -0,0 +1 @@
0.0.5

View file

@ -1 +1 @@
1.22.0 1.25.0

View file

@ -1 +1 @@
13.6.0 13.7.0

View file

@ -1 +1 @@
8.39.0 8.46.0

38
Gemfile
View file

@ -21,13 +21,13 @@ gem 'pg', '~> 1.1'
gem 'rugged', '~> 0.28' gem 'rugged', '~> 0.28'
gem 'grape-path-helpers', '~> 1.3' gem 'grape-path-helpers', '~> 1.3'
gem 'faraday', '~> 0.12' gem 'faraday', '~> 1.0'
gem 'marginalia', '~> 1.8.0' gem 'marginalia', '~> 1.9.0'
# Authentication libraries # Authentication libraries
gem 'devise', '~> 4.6' gem 'devise', '~> 4.6'
gem 'doorkeeper', '~> 5.0.3' gem 'doorkeeper', '~> 5.3.0'
gem 'doorkeeper-openid_connect', '~> 1.6.3' gem 'doorkeeper-openid_connect', '~> 1.7.4'
gem 'omniauth', '~> 1.8' gem 'omniauth', '~> 1.8'
gem 'omniauth-auth0', '~> 2.0.0' gem 'omniauth-auth0', '~> 2.0.0'
gem 'omniauth-azure-oauth2', '~> 0.0.9' gem 'omniauth-azure-oauth2', '~> 0.0.9'
@ -45,6 +45,7 @@ gem 'omniauth_crowd', '~> 2.4.0'
gem 'omniauth-authentiq', '~> 0.3.3' gem 'omniauth-authentiq', '~> 0.3.3'
gem 'omniauth_openid_connect', '~> 0.3.5' gem 'omniauth_openid_connect', '~> 0.3.5'
gem 'omniauth-salesforce', '~> 1.0.5' gem 'omniauth-salesforce', '~> 1.0.5'
gem 'omniauth-atlassian-oauth2', '~> 0.2.0'
gem 'rack-oauth2', '~> 1.9.3' gem 'rack-oauth2', '~> 1.9.3'
gem 'jwt', '~> 2.1.0' gem 'jwt', '~> 2.1.0'
@ -88,12 +89,12 @@ gem 'grape-entity', '~> 0.7.1'
gem 'rack-cors', '~> 1.0.6', require: 'rack/cors' gem 'rack-cors', '~> 1.0.6', require: 'rack/cors'
# GraphQL API # GraphQL API
gem 'graphql', '~> 1.10.5' gem 'graphql', '~> 1.11.4'
# NOTE: graphiql-rails v1.5+ doesn't work: https://gitlab.com/gitlab-org/gitlab/issues/31771 # NOTE: graphiql-rails v1.5+ doesn't work: https://gitlab.com/gitlab-org/gitlab/issues/31771
# TODO: remove app/views/graphiql/rails/editors/show.html.erb when https://github.com/rmosolgo/graphiql-rails/pull/71 is released: # TODO: remove app/views/graphiql/rails/editors/show.html.erb when https://github.com/rmosolgo/graphiql-rails/pull/71 is released:
# https://gitlab.com/gitlab-org/gitlab/issues/31747 # https://gitlab.com/gitlab-org/gitlab/issues/31747
gem 'graphiql-rails', '~> 1.4.10' gem 'graphiql-rails', '~> 1.4.10'
gem 'apollo_upload_server', '~> 2.0.0.beta3' gem 'apollo_upload_server', '~> 2.0.2'
gem 'graphql-docs', '~> 1.6.0', group: [:development, :test] gem 'graphql-docs', '~> 1.6.0', group: [:development, :test]
# Disable strong_params so that Mash does not respond to :permitted? # Disable strong_params so that Mash does not respond to :permitted?
@ -119,7 +120,7 @@ gem 'fog-local', '~> 0.6'
gem 'fog-openstack', '~> 1.0' gem 'fog-openstack', '~> 1.0'
gem 'fog-rackspace', '~> 0.1.1' gem 'fog-rackspace', '~> 0.1.1'
gem 'fog-aliyun', '~> 0.3' gem 'fog-aliyun', '~> 0.3'
gem 'gitlab-fog-azure-rm', '~> 0.7', require: false gem 'gitlab-fog-azure-rm', '~> 1.0', require: false
# for Google storage # for Google storage
gem 'google-api-client', '~> 0.33' gem 'google-api-client', '~> 0.33'
@ -133,7 +134,7 @@ gem 'seed-fu', '~> 2.3.7'
# Search # Search
gem 'elasticsearch-model', '~> 6.1' gem 'elasticsearch-model', '~> 6.1'
gem 'elasticsearch-rails', '~> 6.1', require: 'elasticsearch/rails/instrumentation' gem 'elasticsearch-rails', '~> 6.1', require: 'elasticsearch/rails/instrumentation'
gem 'elasticsearch-api', '~> 6.8' gem 'elasticsearch-api', '~> 6.8.2'
gem 'aws-sdk-core', '~> 3' gem 'aws-sdk-core', '~> 3'
gem 'aws-sdk-cloudformation', '~> 1' gem 'aws-sdk-cloudformation', '~> 1'
gem 'aws-sdk-s3', '~> 1' gem 'aws-sdk-s3', '~> 1'
@ -249,9 +250,7 @@ gem 'slack-messenger', '~> 2.3.3'
gem 'hangouts-chat', '~> 0.0.5' gem 'hangouts-chat', '~> 0.0.5'
# Asana integration # Asana integration
# asana 0.10.1 needs faraday 1.0 gem 'asana', '0.10.2'
# https://gitlab.com/gitlab-org/gitlab/-/issues/224296
gem 'asana', '0.10.0'
# FogBugz integration # FogBugz integration
gem 'ruby-fogbugz', '~> 0.2.1' gem 'ruby-fogbugz', '~> 0.2.1'
@ -260,7 +259,7 @@ gem 'ruby-fogbugz', '~> 0.2.1'
gem 'kubeclient', '~> 4.6.0' gem 'kubeclient', '~> 4.6.0'
# Sanitize user input # Sanitize user input
gem 'sanitize', '~> 4.6' gem 'sanitize', '~> 5.2.1'
gem 'babosa', '~> 1.0.2' gem 'babosa', '~> 1.0.2'
# Sanitizes SVG input # Sanitizes SVG input
@ -304,7 +303,7 @@ gem "gitlab-license", "~> 1.0"
gem 'rack-attack', '~> 6.3.0' gem 'rack-attack', '~> 6.3.0'
# Sentry integration # Sentry integration
gem 'sentry-raven', '~> 2.9' gem 'sentry-raven', '~> 3.0'
gem 'premailer-rails', '~> 1.10.3' gem 'premailer-rails', '~> 1.10.3'
@ -316,7 +315,7 @@ gem 'ruby_parser', '~> 3.8', require: false
gem 'rails-i18n', '~> 6.0' gem 'rails-i18n', '~> 6.0'
gem 'gettext_i18n_rails', '~> 1.8.0' gem 'gettext_i18n_rails', '~> 1.8.0'
gem 'gettext_i18n_rails_js', '~> 1.3' gem 'gettext_i18n_rails_js', '~> 1.3'
gem 'gettext', '~> 3.2.2', require: false, group: :development gem 'gettext', '~> 3.3', require: false, group: :development
gem 'batch-loader', '~> 1.4.0' gem 'batch-loader', '~> 1.4.0'
@ -328,7 +327,7 @@ gem 'snowplow-tracker', '~> 0.6.1'
# Metrics # Metrics
group :metrics do group :metrics do
gem 'method_source', '~> 0.8', require: false gem 'method_source', '~> 1.0', require: false
# Prometheus # Prometheus
gem 'prometheus-client-mmap', '~> 0.11.0' gem 'prometheus-client-mmap', '~> 0.11.0'
@ -337,21 +336,20 @@ end
group :development do group :development do
gem 'brakeman', '~> 4.2', require: false gem 'brakeman', '~> 4.2', require: false
gem 'danger', '~> 6.0', require: false gem 'danger', '~> 8.0', require: false
gem 'letter_opener_web', '~> 1.3.4' gem 'letter_opener_web', '~> 1.3.4'
# Better errors handler # Better errors handler
gem 'better_errors', '~> 2.7.1' gem 'better_errors', '~> 2.7.1'
gem 'binding_of_caller', '~> 0.8.0'
# thin instead webrick # thin instead webrick
gem 'thin', '~> 1.7.0' gem 'thin', '~> 1.7.0'
end end
group :development, :test do group :development, :test do
gem 'bullet', '~> 6.0.2' gem 'bullet', '~> 6.1.0'
gem 'pry-byebug', '~> 3.5.1', platform: :mri gem 'pry-byebug', '~> 3.9.0', platform: :mri
gem 'pry-rails', '~> 0.3.9' gem 'pry-rails', '~> 0.3.9'
gem 'awesome_print', require: false gem 'awesome_print', require: false
@ -512,3 +510,5 @@ gem 'json_schemer', '~> 0.2.12'
gem 'oj', '~> 3.10.6' gem 'oj', '~> 3.10.6'
gem 'multi_json', '~> 1.14.1' gem 'multi_json', '~> 1.14.1'
gem 'yajl-ruby', '~> 1.4.1', require: 'yajl' gem 'yajl-ruby', '~> 1.4.1', require: 'yajl'
gem 'webauthn', '~> 2.3'

View file

@ -73,12 +73,13 @@ GEM
public_suffix (>= 2.0.2, < 5.0) public_suffix (>= 2.0.2, < 5.0)
aes_key_wrap (1.0.1) aes_key_wrap (1.0.1)
akismet (3.0.0) akismet (3.0.0)
apollo_upload_server (2.0.0.beta.3) android_key_attestation (0.3.0)
apollo_upload_server (2.0.2)
graphql (>= 1.8) graphql (>= 1.8)
rails (>= 4.2) rails (>= 4.2)
asana (0.10.0) asana (0.10.2)
faraday (~> 0.9) faraday (~> 1.0)
faraday_middleware (~> 0.9) faraday_middleware (~> 1.0)
faraday_middleware-multi_json (~> 0.0) faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.4) oauth2 (~> 1.4)
asciidoctor (2.0.10) asciidoctor (2.0.10)
@ -93,6 +94,7 @@ GEM
encryptor (~> 3.0.0) encryptor (~> 3.0.0)
attr_required (1.0.1) attr_required (1.0.1)
awesome_print (1.8.0) awesome_print (1.8.0)
awrence (1.1.1)
aws-eventstream (1.1.0) aws-eventstream (1.1.0)
aws-partitions (1.345.0) aws-partitions (1.345.0)
aws-sdk-cloudformation (1.41.0) aws-sdk-cloudformation (1.41.0)
@ -112,15 +114,13 @@ GEM
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
aws-sigv4 (1.2.1) aws-sigv4 (1.2.1)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
azure-core (0.1.15) azure-storage-blob (2.0.0)
faraday (~> 0.9) azure-storage-common (~> 2.0)
faraday_middleware (~> 0.10) nokogiri (~> 1.10.4)
nokogiri (~> 1.6) azure-storage-common (2.0.1)
azure-storage (0.15.0.preview) faraday (~> 1.0)
azure-core (~> 0.1) faraday_middleware (~> 1.0.0.rc1)
faraday (~> 0.9) nokogiri (~> 1.10.4)
faraday_middleware (~> 0.10)
nokogiri (~> 1.6, >= 1.6.8)
babosa (1.0.2) babosa (1.0.2)
base32 (0.3.2) base32 (0.3.2)
batch-loader (1.4.0) batch-loader (1.4.0)
@ -135,8 +135,6 @@ GEM
rack (>= 0.9.0) rack (>= 0.9.0)
bindata (2.4.3) bindata (2.4.3)
binding_ninja (0.2.3) binding_ninja (0.2.3)
binding_of_caller (0.8.0)
debug_inspector (>= 0.0.1)
bootsnap (1.4.6) bootsnap (1.4.6)
msgpack (~> 1.0) msgpack (~> 1.0)
bootstrap_form (4.2.0) bootstrap_form (4.2.0)
@ -145,13 +143,13 @@ GEM
brakeman (4.2.1) brakeman (4.2.1)
browser (4.2.0) browser (4.2.0)
builder (3.2.4) builder (3.2.4)
bullet (6.0.2) bullet (6.1.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
uniform_notifier (~> 1.11) uniform_notifier (~> 1.11)
bundler-audit (0.6.1) bundler-audit (0.6.1)
bundler (>= 1.2.0, < 3) bundler (>= 1.2.0, < 3)
thor (~> 0.18) thor (~> 0.18)
byebug (9.1.0) byebug (11.1.3)
capybara (3.33.0) capybara (3.33.0)
addressable addressable
mini_mime (>= 0.1.3) mini_mime (>= 0.1.3)
@ -167,6 +165,7 @@ GEM
activemodel (>= 4.0.0) activemodel (>= 4.0.0)
activesupport (>= 4.0.0) activesupport (>= 4.0.0)
mime-types (>= 1.16) mime-types (>= 1.16)
cbor (0.5.9.6)
character_set (1.4.0) character_set (1.4.0)
charlock_holmes (0.7.6) charlock_holmes (0.7.6)
childprocess (3.0.0) childprocess (3.0.0)
@ -177,7 +176,7 @@ GEM
cork cork
nap nap
open4 (~> 1.3) open4 (~> 1.3)
coderay (1.1.2) coderay (1.1.3)
colored2 (3.1.2) colored2 (3.1.2)
commonmarker (0.20.1) commonmarker (0.20.1)
ruby-enum (~> 0.5) ruby-enum (~> 0.5)
@ -189,6 +188,9 @@ GEM
contracts (0.11.0) contracts (0.11.0)
cork (0.3.0) cork (0.3.0)
colored2 (~> 3.1) colored2 (~> 3.1)
cose (1.0.0)
cbor (~> 0.5.9)
openssl-signature_algorithm (~> 0.4.0)
countries (3.0.0) countries (3.0.0)
i18n_data (~> 0.8.0) i18n_data (~> 0.8.0)
sixarm_ruby_unaccent (~> 1.1) sixarm_ruby_unaccent (~> 1.1)
@ -200,21 +202,20 @@ GEM
css_parser (1.7.0) css_parser (1.7.0)
addressable addressable
daemons (1.2.6) daemons (1.2.6)
danger (6.0.9) danger (8.0.5)
claide (~> 1.0) claide (~> 1.0)
claide-plugins (>= 0.9.2) claide-plugins (>= 0.9.2)
colored2 (~> 3.1) colored2 (~> 3.1)
cork (~> 0.1) cork (~> 0.1)
faraday (~> 0.9) faraday (>= 0.9.0, < 2.0)
faraday-http-cache (~> 2.0) faraday-http-cache (~> 2.0)
git (~> 1.5) git (~> 1.7)
kramdown (~> 2.0) kramdown (~> 2.3)
kramdown-parser-gfm (~> 1.0) kramdown-parser-gfm (~> 1.0)
no_proxy_fix no_proxy_fix
octokit (~> 4.7) octokit (~> 4.7)
terminal-table (~> 1) terminal-table (~> 1)
database_cleaner (1.7.0) database_cleaner (1.7.0)
debug_inspector (0.0.3)
debugger-ruby_core_source (1.3.8) debugger-ruby_core_source (1.3.8)
deckar01-task_list (2.3.1) deckar01-task_list (2.3.1)
html-pipeline html-pipeline
@ -254,11 +255,11 @@ GEM
docile (1.3.2) docile (1.3.2)
domain_name (0.5.20180417) domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
doorkeeper (5.0.3) doorkeeper (5.3.3)
railties (>= 4.2) railties (>= 5)
doorkeeper-openid_connect (1.6.3) doorkeeper-openid_connect (1.7.4)
doorkeeper (>= 5.0, < 5.2) doorkeeper (>= 5.2, < 5.5)
json-jwt (~> 1.6) json-jwt (>= 1.11.0)
dry-configurable (0.11.5) dry-configurable (0.11.5)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
dry-core (~> 0.4, >= 0.4.7) dry-core (~> 0.4, >= 0.4.7)
@ -284,18 +285,18 @@ GEM
ecma-re-validator (0.2.1) ecma-re-validator (0.2.1)
regexp_parser (~> 1.2) regexp_parser (~> 1.2)
ed25519 (1.2.4) ed25519 (1.2.4)
elasticsearch (6.8.0) elasticsearch (6.8.2)
elasticsearch-api (= 6.8.0) elasticsearch-api (= 6.8.2)
elasticsearch-transport (= 6.8.0) elasticsearch-transport (= 6.8.2)
elasticsearch-api (6.8.0) elasticsearch-api (6.8.2)
multi_json multi_json
elasticsearch-model (6.1.0) elasticsearch-model (6.1.1)
activesupport (> 3) activesupport (> 3)
elasticsearch (> 1) elasticsearch (~> 6)
hashie hashie
elasticsearch-rails (6.1.0) elasticsearch-rails (6.1.1)
elasticsearch-transport (6.8.0) elasticsearch-transport (6.8.2)
faraday faraday (~> 1)
multi_json multi_json
email_reply_trimmer (0.1.6) email_reply_trimmer (0.1.6)
email_spec (2.2.0) email_spec (2.2.0)
@ -320,15 +321,15 @@ GEM
factory_bot_rails (5.1.0) factory_bot_rails (5.1.0)
factory_bot (~> 5.1.0) factory_bot (~> 5.1.0)
railties (>= 4.2.0) railties (>= 4.2.0)
faraday (0.17.3) faraday (1.0.1)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6) faraday-cookie_jar (0.0.7)
faraday (>= 0.7.4) faraday (>= 0.8.0)
http-cookie (~> 1.0.0) http-cookie (~> 1.0.0)
faraday-http-cache (2.0.0) faraday-http-cache (2.2.0)
faraday (~> 0.8) faraday (>= 0.8)
faraday_middleware (0.14.0) faraday_middleware (1.0.0)
faraday (>= 0.7.4, < 1.0) faraday (~> 1.0)
faraday_middleware-aws-sigv4 (0.3.0) faraday_middleware-aws-sigv4 (0.3.0)
aws-sigv4 (~> 1.0) aws-sigv4 (~> 1.0)
faraday (>= 0.15) faraday (>= 0.15)
@ -338,7 +339,7 @@ GEM
fast_blank (1.0.0) fast_blank (1.0.0)
fast_gettext (1.6.0) fast_gettext (1.6.0)
ffaker (2.10.0) ffaker (2.10.0)
ffi (1.12.2) ffi (1.13.1)
ffi-compiler (1.0.1) ffi-compiler (1.0.1)
ffi (>= 1.0.0) ffi (>= 1.0.0)
rake rake
@ -403,7 +404,7 @@ GEM
json json
get_process_mem (0.2.5) get_process_mem (0.2.5)
ffi (~> 1.0) ffi (~> 1.0)
gettext (3.2.9) gettext (3.3.6)
locale (>= 2.0.5) locale (>= 2.0.5)
text (>= 1.3.0) text (>= 1.3.0)
gettext_i18n_rails (1.8.0) gettext_i18n_rails (1.8.0)
@ -413,14 +414,16 @@ 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)
git (1.5.0) git (1.7.0)
rchardet (~> 1.8)
gitaly (13.3.0.pre.rc2) gitaly (13.3.0.pre.rc2)
grpc (~> 1.0) grpc (~> 1.0)
github-markup (1.7.0) github-markup (1.7.0)
gitlab-chronic (0.10.5) gitlab-chronic (0.10.5)
numerizer (~> 0.2) numerizer (~> 0.2)
gitlab-fog-azure-rm (0.7.0) gitlab-fog-azure-rm (1.0.0)
azure-storage (~> 0.15.0.preview) azure-storage-blob (~> 2.0)
azure-storage-common (~> 2.0)
fog-core (= 2.1.0) fog-core (= 2.1.0)
fog-json (~> 1.2.0) fog-json (~> 1.2.0)
mime-types mime-types
@ -436,7 +439,7 @@ GEM
gitlab-mail_room (0.0.6) gitlab-mail_room (0.0.6)
gitlab-markup (1.7.1) gitlab-markup (1.7.1)
gitlab-net-dns (0.9.1) gitlab-net-dns (0.9.1)
gitlab-puma (4.3.3.gitlab.2) gitlab-puma (4.3.5.gitlab.3)
nio4r (~> 2.0) nio4r (~> 2.0)
gitlab-puma_worker_killer (0.1.1.gitlab.1) gitlab-puma_worker_killer (0.1.1.gitlab.1)
get_process_mem (~> 0.2) get_process_mem (~> 0.2)
@ -502,7 +505,7 @@ GEM
graphiql-rails (1.4.10) graphiql-rails (1.4.10)
railties railties
sprockets-rails sprockets-rails
graphql (1.10.5) graphql (1.11.4)
graphql-docs (1.6.0) graphql-docs (1.6.0)
commonmarker (~> 0.16) commonmarker (~> 0.16)
escape_utils (~> 1.2) escape_utils (~> 1.2)
@ -516,7 +519,7 @@ GEM
googleapis-common-protos-types (~> 1.0) googleapis-common-protos-types (~> 1.0)
gssapi (1.2.0) gssapi (1.2.0)
ffi (>= 1.0.1) ffi (>= 1.0.1)
guard (2.15.1) guard (2.16.2)
formatador (>= 0.2.4) formatador (>= 0.2.4)
listen (>= 2.7, < 4.0) listen (>= 2.7, < 4.0)
lumberjack (>= 1.0.12, < 2.0) lumberjack (>= 1.0.12, < 2.0)
@ -649,11 +652,10 @@ GEM
xml-simple xml-simple
licensee (8.9.2) licensee (8.9.2)
rugged (~> 0.24) rugged (~> 0.24)
listen (3.1.5) listen (3.2.1)
rb-fsevent (~> 0.9, >= 0.9.4) rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.7) rb-inotify (~> 0.9, >= 0.9.10)
ruby_dep (~> 1.2) locale (2.1.3)
locale (2.1.2)
lockbox (0.3.3) lockbox (0.3.3)
lograge (0.11.2) lograge (0.11.2)
actionpack (>= 4) actionpack (>= 4)
@ -664,19 +666,19 @@ GEM
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
lru_redux (1.1.0) lru_redux (1.1.0)
lumberjack (1.0.13) lumberjack (1.2.7)
mail (2.7.1) mail (2.7.1)
mini_mime (>= 0.1.1) mini_mime (>= 0.1.1)
marcel (0.3.3) marcel (0.3.3)
mimemagic (~> 0.3.2) mimemagic (~> 0.3.2)
marginalia (1.8.0) marginalia (1.9.0)
actionpack (>= 2.3) actionpack (>= 2.3)
activerecord (>= 2.3) activerecord (>= 2.3)
memoist (0.16.0) memoist (0.16.0)
memoizable (0.4.2) memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1) thread_safe (~> 0.3, >= 0.3.1)
memory_profiler (0.9.14) memory_profiler (0.9.14)
method_source (0.9.2) method_source (1.0.0)
mime-types (3.3.1) mime-types (3.3.1)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2020.0512) mime-types-data (3.2020.0512)
@ -695,7 +697,7 @@ GEM
faraday (>= 0.9, < 2.0.0) faraday (>= 0.9, < 2.0.0)
faraday-cookie_jar (~> 0.0.6) faraday-cookie_jar (~> 0.0.6)
ms_rest (~> 0.7.6) ms_rest (~> 0.7.6)
msgpack (1.3.1) msgpack (1.3.3)
multi_json (1.14.1) multi_json (1.14.1)
multi_xml (0.6.0) multi_xml (0.6.0)
multipart-post (2.1.1) multipart-post (2.1.1)
@ -713,10 +715,10 @@ GEM
netrc (0.11.0) netrc (0.11.0)
nio4r (2.5.2) nio4r (2.5.2)
no_proxy_fix (0.1.2) no_proxy_fix (0.1.2)
nokogiri (1.10.9) nokogiri (1.10.10)
mini_portile2 (~> 2.4.0) mini_portile2 (~> 2.4.0)
nokogumbo (1.5.0) nokogumbo (2.0.2)
nokogiri nokogiri (~> 1.8, >= 1.8.4)
notiffany (0.1.3) notiffany (0.1.3)
nenv (~> 0.1) nenv (~> 0.1)
shellany (~> 0.0) shellany (~> 0.0)
@ -735,6 +737,9 @@ GEM
omniauth (1.9.0) omniauth (1.9.0)
hashie (>= 3.4.6, < 3.7.0) hashie (>= 3.4.6, < 3.7.0)
rack (>= 1.6.2, < 3) rack (>= 1.6.2, < 3)
omniauth-atlassian-oauth2 (0.2.0)
omniauth (>= 1.1.1)
omniauth-oauth2 (>= 1.5)
omniauth-auth0 (2.0.0) omniauth-auth0 (2.0.0)
omniauth-oauth2 (~> 1.4) omniauth-oauth2 (~> 1.4)
omniauth-authentiq (0.3.3) omniauth-authentiq (0.3.3)
@ -803,8 +808,10 @@ GEM
validate_email validate_email
validate_url validate_url
webfinger (>= 1.0.1) webfinger (>= 1.0.1)
openssl (2.2.0)
openssl-signature_algorithm (0.4.0)
opentracing (0.5.0) opentracing (0.5.0)
optimist (3.0.0) optimist (3.0.1)
org-ruby (0.9.12) org-ruby (0.9.12)
rubypants (~> 0.2) rubypants (~> 0.2)
orm_adapter (0.5.0) orm_adapter (0.5.0)
@ -815,7 +822,7 @@ GEM
parslet (1.8.2) parslet (1.8.2)
peek (1.1.0) peek (1.1.0)
railties (>= 4.0.0) railties (>= 4.0.0)
pg (1.2.2) pg (1.2.3)
png_quantizator (0.2.1) png_quantizator (0.2.1)
po_to_json (1.0.1) po_to_json (1.0.1)
json (>= 1.6.0) json (>= 1.6.0)
@ -832,12 +839,12 @@ GEM
unparser unparser
procto (0.0.3) procto (0.0.3)
prometheus-client-mmap (0.11.0) prometheus-client-mmap (0.11.0)
pry (0.11.3) pry (0.13.1)
coderay (~> 1.1.0) coderay (~> 1.1)
method_source (~> 0.9.0) method_source (~> 1.0)
pry-byebug (3.5.1) pry-byebug (3.9.0)
byebug (~> 9.1) byebug (~> 11.0)
pry (~> 0.10) pry (~> 0.13.0)
pry-rails (0.3.9) pry-rails (0.3.9)
pry (>= 0.10.4) pry (>= 0.10.4)
public_suffix (4.0.3) public_suffix (4.0.3)
@ -899,15 +906,16 @@ GEM
rainbow (3.0.0) rainbow (3.0.0)
raindrops (0.19.1) raindrops (0.19.1)
rake (12.3.3) rake (12.3.3)
rb-fsevent (0.10.2) rb-fsevent (0.10.4)
rb-inotify (0.9.10) rb-inotify (0.10.1)
ffi (>= 0.5.0, < 2) ffi (~> 1.0)
rblineprof (0.3.6) rblineprof (0.3.6)
debugger-ruby_core_source (~> 1.3) debugger-ruby_core_source (~> 1.3)
rbtrace (0.4.11) rbtrace (0.4.14)
ffi (>= 1.0.6) ffi (>= 1.0.6)
msgpack (>= 0.4.3) msgpack (>= 0.4.3)
optimist (>= 3.0.0) optimist (>= 3.0.0)
rchardet (1.8.0)
rdoc (6.1.2) rdoc (6.1.2)
re2 (1.2.0) re2 (1.2.0)
recaptcha (4.13.1) recaptcha (4.13.1)
@ -1020,7 +1028,6 @@ GEM
nokogiri (>= 1.5.10) nokogiri (>= 1.5.10)
ruby-statistics (2.1.2) ruby-statistics (2.1.2)
ruby2_keywords (0.0.2) ruby2_keywords (0.0.2)
ruby_dep (1.5.0)
ruby_parser (3.13.1) ruby_parser (3.13.1)
sexp_processor (~> 4.9) sexp_processor (~> 4.9)
rubyntlm (0.6.2) rubyntlm (0.6.2)
@ -1028,10 +1035,12 @@ GEM
rubyzip (2.0.0) rubyzip (2.0.0)
rugged (0.28.4.1) rugged (0.28.4.1)
safe_yaml (1.0.4) safe_yaml (1.0.4)
sanitize (4.6.6) safety_net_attestation (0.4.0)
jwt (~> 2.0)
sanitize (5.2.1)
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.4.4) nokogiri (>= 1.8.0)
nokogumbo (~> 1.4) nokogumbo (~> 2.0)
sass (3.5.5) sass (3.5.5)
sass-listen (~> 4.0.0) sass-listen (~> 4.0.0)
sass-listen (4.0.0) sass-listen (4.0.0)
@ -1052,14 +1061,15 @@ GEM
scss_lint (0.56.0) scss_lint (0.56.0)
rake (>= 0.9, < 13) rake (>= 0.9, < 13)
sass (~> 3.5.3) sass (~> 3.5.3)
securecompare (1.0.0)
seed-fu (2.3.7) seed-fu (2.3.7)
activerecord (>= 3.1) activerecord (>= 3.1)
activesupport (>= 3.1) activesupport (>= 3.1)
selenium-webdriver (3.142.6) selenium-webdriver (3.142.6)
childprocess (>= 0.5, < 4.0) childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2) rubyzip (>= 1.2.2)
sentry-raven (2.9.0) sentry-raven (3.0.4)
faraday (>= 0.7.6, < 1.0) faraday (>= 1.0)
settingslogic (2.0.9) settingslogic (2.0.9)
sexp_processor (4.12.0) sexp_processor (4.12.0)
shellany (0.0.1) shellany (0.0.1)
@ -1137,6 +1147,9 @@ GEM
parslet (~> 1.8.0) parslet (~> 1.8.0)
toml-rb (1.0.0) toml-rb (1.0.0)
citrus (~> 3.0, > 3.0) citrus (~> 3.0, > 3.0)
tpm-key_attestation (0.9.0)
bindata (~> 2.4)
openssl-signature_algorithm (~> 0.4.0)
truncato (0.7.11) truncato (0.7.11)
htmlentities (~> 4.3.1) htmlentities (~> 4.3.1)
nokogiri (>= 1.7.0, <= 2.0) nokogiri (>= 1.7.0, <= 2.0)
@ -1188,6 +1201,16 @@ GEM
vmstat (2.3.0) vmstat (2.3.0)
warden (1.2.8) warden (1.2.8)
rack (>= 2.0.6) rack (>= 2.0.6)
webauthn (2.3.0)
android_key_attestation (~> 0.3.0)
awrence (~> 1.1)
bindata (~> 2.4)
cbor (~> 0.5.9)
cose (~> 1.0)
openssl (~> 2.0)
safety_net_attestation (~> 0.4.0)
securecompare (~> 1.0)
tpm-key_attestation (~> 0.9.0)
webfinger (1.1.0) webfinger (1.1.0)
activesupport activesupport
httpclient (>= 2.4) httpclient (>= 2.4)
@ -1222,8 +1245,8 @@ DEPENDENCIES
acts-as-taggable-on (~> 6.0) acts-as-taggable-on (~> 6.0)
addressable (~> 2.7) addressable (~> 2.7)
akismet (~> 3.0) akismet (~> 3.0)
apollo_upload_server (~> 2.0.0.beta3) apollo_upload_server (~> 2.0.2)
asana (= 0.10.0) asana (= 0.10.2)
asciidoctor (~> 2.0.10) asciidoctor (~> 2.0.10)
asciidoctor-include-ext (~> 0.3.1) asciidoctor-include-ext (~> 0.3.1)
asciidoctor-plantuml (~> 0.0.12) asciidoctor-plantuml (~> 0.0.12)
@ -1240,12 +1263,11 @@ DEPENDENCIES
benchmark-ips (~> 2.3.0) benchmark-ips (~> 2.3.0)
benchmark-memory (~> 0.1) benchmark-memory (~> 0.1)
better_errors (~> 2.7.1) better_errors (~> 2.7.1)
binding_of_caller (~> 0.8.0)
bootsnap (~> 1.4.6) bootsnap (~> 1.4.6)
bootstrap_form (~> 4.2.0) bootstrap_form (~> 4.2.0)
brakeman (~> 4.2) brakeman (~> 4.2)
browser (~> 4.2) browser (~> 4.2)
bullet (~> 6.0.2) bullet (~> 6.1.0)
bundler-audit (~> 0.6.1) bundler-audit (~> 0.6.1)
capybara (~> 3.33.0) capybara (~> 3.33.0)
capybara-screenshot (~> 1.0.22) capybara-screenshot (~> 1.0.22)
@ -1256,7 +1278,7 @@ DEPENDENCIES
connection_pool (~> 2.0) connection_pool (~> 2.0)
countries (~> 3.0) countries (~> 3.0)
creole (~> 0.5.0) creole (~> 0.5.0)
danger (~> 6.0) danger (~> 8.0)
database_cleaner (~> 1.7.0) database_cleaner (~> 1.7.0)
deckar01-task_list (= 2.3.1) deckar01-task_list (= 2.3.1)
default_value_for (~> 3.3.0) default_value_for (~> 3.3.0)
@ -1267,10 +1289,10 @@ DEPENDENCIES
diff_match_patch (~> 0.1.0) diff_match_patch (~> 0.1.0)
diffy (~> 3.3) diffy (~> 3.3)
discordrb-webhooks-blackst0ne (~> 3.3) discordrb-webhooks-blackst0ne (~> 3.3)
doorkeeper (~> 5.0.3) doorkeeper (~> 5.3.0)
doorkeeper-openid_connect (~> 1.6.3) doorkeeper-openid_connect (~> 1.7.4)
ed25519 (~> 1.2) ed25519 (~> 1.2)
elasticsearch-api (~> 6.8) elasticsearch-api (~> 6.8.2)
elasticsearch-model (~> 6.1) elasticsearch-model (~> 6.1)
elasticsearch-rails (~> 6.1) elasticsearch-rails (~> 6.1)
email_reply_trimmer (~> 0.1) email_reply_trimmer (~> 0.1)
@ -1278,7 +1300,7 @@ DEPENDENCIES
erubi (~> 1.9.0) erubi (~> 1.9.0)
escape_utils (~> 1.1) escape_utils (~> 1.1)
factory_bot_rails (~> 5.1.0) factory_bot_rails (~> 5.1.0)
faraday (~> 0.12) faraday (~> 1.0)
faraday_middleware-aws-sigv4 (~> 0.3.0) faraday_middleware-aws-sigv4 (~> 0.3.0)
fast_blank fast_blank
ffaker (~> 2.10) ffaker (~> 2.10)
@ -1297,13 +1319,13 @@ DEPENDENCIES
fugit (~> 1.2.1) fugit (~> 1.2.1)
fuubar (~> 2.2.0) fuubar (~> 2.2.0)
gemojione (~> 3.3) gemojione (~> 3.3)
gettext (~> 3.2.2) gettext (~> 3.3)
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 (~> 13.3.0.pre.rc1) gitaly (~> 13.3.0.pre.rc1)
github-markup (~> 1.7.0) github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5) gitlab-chronic (~> 0.10.5)
gitlab-fog-azure-rm (~> 0.7) gitlab-fog-azure-rm (~> 1.0)
gitlab-labkit (= 0.12.1) gitlab-labkit (= 0.12.1)
gitlab-license (~> 1.0) gitlab-license (~> 1.0)
gitlab-mail_room (~> 0.0.6) gitlab-mail_room (~> 0.0.6)
@ -1324,7 +1346,7 @@ DEPENDENCIES
grape-path-helpers (~> 1.3) grape-path-helpers (~> 1.3)
grape_logging (~> 1.7) grape_logging (~> 1.7)
graphiql-rails (~> 1.4.10) graphiql-rails (~> 1.4.10)
graphql (~> 1.10.5) graphql (~> 1.11.4)
graphql-docs (~> 1.6.0) graphql-docs (~> 1.6.0)
grpc (~> 1.30.2) grpc (~> 1.30.2)
gssapi gssapi
@ -1358,9 +1380,9 @@ DEPENDENCIES
loofah (~> 2.2) loofah (~> 2.2)
lru_redux lru_redux
mail (= 2.7.1) mail (= 2.7.1)
marginalia (~> 1.8.0) marginalia (~> 1.9.0)
memory_profiler (~> 0.9) memory_profiler (~> 0.9)
method_source (~> 0.8) method_source (~> 1.0)
mimemagic (~> 0.3.2) mimemagic (~> 0.3.2)
mini_magick mini_magick
minitest (~> 5.11.0) minitest (~> 5.11.0)
@ -1374,6 +1396,7 @@ DEPENDENCIES
octokit (~> 4.15) octokit (~> 4.15)
oj (~> 3.10.6) oj (~> 3.10.6)
omniauth (~> 1.8) omniauth (~> 1.8)
omniauth-atlassian-oauth2 (~> 0.2.0)
omniauth-auth0 (~> 2.0.0) omniauth-auth0 (~> 2.0.0)
omniauth-authentiq (~> 0.3.3) omniauth-authentiq (~> 0.3.3)
omniauth-azure-oauth2 (~> 0.0.9) omniauth-azure-oauth2 (~> 0.0.9)
@ -1397,7 +1420,7 @@ DEPENDENCIES
png_quantizator (~> 0.2.1) png_quantizator (~> 0.2.1)
premailer-rails (~> 1.10.3) premailer-rails (~> 1.10.3)
prometheus-client-mmap (~> 0.11.0) prometheus-client-mmap (~> 0.11.0)
pry-byebug (~> 3.5.1) pry-byebug (~> 3.9.0)
pry-rails (~> 0.3.9) pry-rails (~> 0.3.9)
rack (~> 2.0.9) rack (~> 2.0.9)
rack-attack (~> 6.3.0) rack-attack (~> 6.3.0)
@ -1437,12 +1460,12 @@ DEPENDENCIES
ruby_parser (~> 3.8) ruby_parser (~> 3.8)
rubyzip (~> 2.0.0) rubyzip (~> 2.0.0)
rugged (~> 0.28) rugged (~> 0.28)
sanitize (~> 4.6) sanitize (~> 5.2.1)
sassc-rails (~> 2.1.0) sassc-rails (~> 2.1.0)
scss_lint (~> 0.56.0) scss_lint (~> 0.56.0)
seed-fu (~> 2.3.7) seed-fu (~> 2.3.7)
selenium-webdriver (~> 3.142) selenium-webdriver (~> 3.142)
sentry-raven (~> 2.9) sentry-raven (~> 3.0)
settingslogic (~> 2.0.9) settingslogic (~> 2.0.9)
shoulda-matchers (~> 4.0.1) shoulda-matchers (~> 4.0.1)
sidekiq (~> 5.2.7) sidekiq (~> 5.2.7)
@ -1474,6 +1497,7 @@ DEPENDENCIES
validates_hostname (~> 1.0.10) validates_hostname (~> 1.0.10)
version_sorter (~> 2.2.4) version_sorter (~> 2.2.4)
vmstat (~> 2.3.0) vmstat (~> 2.3.0)
webauthn (~> 2.3)
webmock (~> 3.5.1) webmock (~> 3.5.1)
webpack-rails (~> 0.9.10) webpack-rails (~> 0.9.10)
wikicloth (= 0.8.1) wikicloth (= 0.8.1)

View file

@ -68,7 +68,7 @@ GitLab is an open source project and we are very happy to accept community contr
To work on GitLab itself, we recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit). To work on GitLab itself, we recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit).
If you do not use the GitLab Development Kit you need to install and setup all the dependencies yourself, this is a lot of work and error prone. If you do not use the GitLab Development Kit you need to install and setup all the dependencies yourself, this is a lot of work and error prone.
One small thing you also have to do when installing it yourself is to copy the example development unicorn configuration file: One small thing you also have to do when installing it yourself is to copy the example development Unicorn configuration file:
cp config/unicorn.rb.example.development config/unicorn.rb cp config/unicorn.rb.example.development config/unicorn.rb
@ -79,9 +79,9 @@ Instructions on how to start GitLab and how to run the tests can be found in the
GitLab is a Ruby on Rails application that runs on the following software: GitLab is a Ruby on Rails application that runs on the following software:
- Ubuntu/Debian/CentOS/RHEL/OpenSUSE - Ubuntu/Debian/CentOS/RHEL/OpenSUSE
- Ruby (MRI) 2.6.5 - Ruby (MRI) 2.6.6
- Git 2.8.4+ - Git 2.24+
- Redis 2.8+ - Redis 4.0+
- PostgreSQL 11+ - PostgreSQL 11+
For more information please see the [architecture](https://docs.gitlab.com/ee/development/architecture.html) and [requirements](https://docs.gitlab.com/ee/install/requirements.html) documentation. For more information please see the [architecture](https://docs.gitlab.com/ee/development/architecture.html) and [requirements](https://docs.gitlab.com/ee/install/requirements.html) documentation.
@ -116,7 +116,7 @@ Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on
## Is it any good? ## Is it any good?
[Yes](https://news.ycombinator.com/item?id=3067434) [Yes](https://about.gitlab.com/is-it-any-good/)
## Is it awesome? ## Is it awesome?

View file

@ -1 +1 @@
13.3.9 13.4.6

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 388 KiB

After

Width:  |  Height:  |  Size: 387 KiB

View file

@ -1,8 +1,7 @@
import PayloadPreviewer from '~/pages/admin/application_settings/payload_previewer'; import PayloadPreviewer from '~/pages/admin/application_settings/payload_previewer';
export default () => { export default () => {
new PayloadPreviewer( Array.from(document.querySelectorAll('.js-payload-preview-trigger')).forEach(trigger => {
document.querySelector('.js-usage-ping-payload-trigger'), new PayloadPreviewer(trigger).init();
document.querySelector('.js-usage-ping-payload'), });
).init();
}; };

View file

@ -0,0 +1,48 @@
<script>
import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui';
export default {
components: {
GlEmptyState,
GlSprintf,
GlLink,
},
inject: {
svgPath: {
type: String,
},
docsLink: {
type: String,
},
primaryButtonPath: {
type: String,
},
},
};
</script>
<template>
<gl-empty-state
class="js-empty-state"
:title="__('Activate user activity analysis')"
:svg-path="svgPath"
:primary-button-text="__('Turn on usage ping')"
:primary-button-link="primaryButtonPath"
>
<template #description>
<gl-sprintf
:message="
__(
'Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}.',
)
"
>
<template #docLink="{content}">
<gl-link :href="docsLink" target="_blank">{{ content }}</gl-link>
</template>
<template #strong="{ content }"
><strong>{{ content }}</strong></template
>
</gl-sprintf>
</template>
</gl-empty-state>
</template>

View file

@ -0,0 +1,53 @@
<script>
import { GlEmptyState, GlSprintf, GlLink, GlButton } from '@gitlab/ui';
export default {
components: {
GlEmptyState,
GlSprintf,
GlLink,
GlButton,
},
inject: {
isAdmin: {
type: Boolean,
},
svgPath: {
type: String,
},
docsLink: {
type: String,
},
primaryButtonPath: {
type: String,
},
},
};
</script>
<template>
<gl-empty-state class="js-empty-state" :title="__('Usage ping is off')" :svg-path="svgPath">
<template #description>
<gl-sprintf
v-if="!isAdmin"
:message="
__(
'To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}.',
)
"
>
<template #docLink="{content}">
<gl-link :href="docsLink" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
<template v-else
><p>
{{ __('Turn on usage ping to review instance-level analytics.') }}
</p>
<gl-button category="primary" variant="success" :href="primaryButtonPath">
{{ __('Turn on usage ping') }}</gl-button
>
</template>
</template>
</gl-empty-state>
</template>

View file

@ -3,7 +3,6 @@
* and returns an array of the following form: * and returns an array of the following form:
* [{ key: "forks", label: "Forks", value: 50 }] * [{ key: "forks", label: "Forks", value: 50 }]
*/ */
// eslint-disable-next-line import/prefer-default-export
export const getStatistics = state => labels => export const getStatistics = state => labels =>
Object.keys(labels).map(key => { Object.keys(labels).map(key => {
const result = { const result = {

View file

@ -1,34 +0,0 @@
import $ from 'jquery';
export default class AjaxLoadingSpinner {
static init() {
const $elements = $('.js-ajax-loading-spinner');
$elements.on('ajax:beforeSend', AjaxLoadingSpinner.ajaxBeforeSend);
$elements.on('ajax:complete', AjaxLoadingSpinner.ajaxComplete);
}
static ajaxBeforeSend(e) {
e.target.setAttribute('disabled', '');
const iconElement = e.target.querySelector('i');
// get first fa- icon
const originalIcon = iconElement.className.match(/(fa-)([^\s]+)/g)[0];
iconElement.dataset.icon = originalIcon;
AjaxLoadingSpinner.toggleLoadingIcon(iconElement);
$(e.target).off('ajax:beforeSend', AjaxLoadingSpinner.ajaxBeforeSend);
}
static ajaxComplete(e) {
e.target.removeAttribute('disabled');
const iconElement = e.target.querySelector('i');
AjaxLoadingSpinner.toggleLoadingIcon(iconElement);
$(e.target).off('ajax:complete', AjaxLoadingSpinner.ajaxComplete);
}
static toggleLoadingIcon(iconElement) {
const { classList } = iconElement;
classList.toggle(iconElement.dataset.icon);
classList.toggle('fa-spinner');
classList.toggle('fa-spin');
}
}

View file

@ -0,0 +1,13 @@
// This allows us to dismiss alerts that we've migrated from bootstrap
// Note: This ONLY works on alerts that are created on page load
// You can follow this effort in the following epic
// https://gitlab.com/groups/gitlab-org/-/epics/4070
export default function initAlertHandler() {
const ALERT_SELECTOR = '.gl-alert';
const CLOSE_SELECTOR = '.gl-alert-dismiss';
const dismissAlert = ({ target }) => target.closest(ALERT_SELECTOR).remove();
const closeButtons = document.querySelectorAll(`${ALERT_SELECTOR} ${CLOSE_SELECTOR}`);
closeButtons.forEach(alert => alert.addEventListener('click', dismissAlert));
}

View file

@ -1,4 +1,5 @@
<script> <script>
/* eslint-disable vue/no-v-html */
import * as Sentry from '@sentry/browser'; import * as Sentry from '@sentry/browser';
import { import {
GlAlert, GlAlert,
@ -9,7 +10,6 @@ import {
GlTabs, GlTabs,
GlTab, GlTab,
GlButton, GlButton,
GlTable,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import alertQuery from '../graphql/queries/details.query.graphql'; import alertQuery from '../graphql/queries/details.query.graphql';
@ -27,6 +27,7 @@ import { toggleContainerClasses } from '~/lib/utils/dom_utils';
import SystemNote from './system_notes/system_note.vue'; import SystemNote from './system_notes/system_note.vue';
import AlertSidebar from './alert_sidebar.vue'; import AlertSidebar from './alert_sidebar.vue';
import AlertMetrics from './alert_metrics.vue'; import AlertMetrics from './alert_metrics.vue';
import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
const containerEl = document.querySelector('.page-with-contextual-sidebar'); const containerEl = document.querySelector('.page-with-contextual-sidebar');
@ -42,18 +43,19 @@ export default {
tabsConfig: [ tabsConfig: [
{ {
id: 'overview', id: 'overview',
title: s__('AlertManagement|Overview'),
},
{
id: 'fullDetails',
title: s__('AlertManagement|Alert details'), title: s__('AlertManagement|Alert details'),
}, },
{ {
id: 'metrics', id: 'metrics',
title: s__('AlertManagement|Metrics'), title: s__('AlertManagement|Metrics'),
}, },
{
id: 'activity',
title: s__('AlertManagement|Activity feed'),
},
], ],
components: { components: {
AlertDetailsTable,
GlBadge, GlBadge,
GlAlert, GlAlert,
GlIcon, GlIcon,
@ -62,7 +64,6 @@ export default {
GlTab, GlTab,
GlTabs, GlTabs,
GlButton, GlButton,
GlTable,
TimeAgoTooltip, TimeAgoTooltip,
AlertSidebar, AlertSidebar,
SystemNote, SystemNote,
@ -330,32 +331,17 @@ export default {
</div> </div>
<div class="gl-pl-2" data-testid="runbook">{{ alert.runbook }}</div> <div class="gl-pl-2" data-testid="runbook">{{ alert.runbook }}</div>
</div> </div>
<template> <alert-details-table :alert="alert" :loading="loading" />
<div v-if="alert.notes.nodes" class="issuable-discussion py-5">
<ul class="notes main-notes-list timeline">
<system-note v-for="note in alert.notes.nodes" :key="note.id" :note="note" />
</ul>
</div>
</template>
</gl-tab> </gl-tab>
<gl-tab :data-testid="$options.tabsConfig[1].id" :title="$options.tabsConfig[1].title"> <gl-tab :data-testid="$options.tabsConfig[1].id" :title="$options.tabsConfig[1].title">
<gl-table <alert-metrics :dashboard-url="alert.metricsDashboardUrl" />
class="alert-management-details-table"
:items="[{ key: 'Value', ...alert }]"
:show-empty="true"
:busy="loading"
stacked
>
<template #empty>
{{ s__('AlertManagement|No alert data to display.') }}
</template>
<template #table-busy>
<gl-loading-icon size="lg" color="dark" class="mt-3" />
</template>
</gl-table>
</gl-tab> </gl-tab>
<gl-tab :data-testid="$options.tabsConfig[2].id" :title="$options.tabsConfig[2].title"> <gl-tab :data-testid="$options.tabsConfig[2].id" :title="$options.tabsConfig[2].title">
<alert-metrics :dashboard-url="alert.metricsDashboardUrl" /> <div v-if="alert.notes.nodes.length > 0" class="issuable-discussion">
<ul class="notes main-notes-list timeline">
<system-note v-for="note in alert.notes.nodes" :key="note.id" :note="note" />
</ul>
</div>
</gl-tab> </gl-tab>
</gl-tabs> </gl-tabs>
<alert-sidebar <alert-sidebar

View file

@ -1,8 +1,12 @@
<script> <script>
/* eslint-disable vue/no-v-html */
import { import {
GlLoadingIcon, GlLoadingIcon,
GlTable, GlTable,
GlAlert, GlAlert,
GlAvatarsInline,
GlAvatarLink,
GlAvatar,
GlIcon, GlIcon,
GlLink, GlLink,
GlTabs, GlTabs,
@ -11,6 +15,7 @@ import {
GlPagination, GlPagination,
GlSearchBoxByType, GlSearchBoxByType,
GlSprintf, GlSprintf,
GlTooltipDirective,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { debounce, trim } from 'lodash'; import { debounce, trim } from 'lodash';
import { __, s__ } from '~/locale'; import { __, s__ } from '~/locale';
@ -35,6 +40,7 @@ const tdClass =
const thClass = 'gl-hover-bg-blue-50'; const thClass = 'gl-hover-bg-blue-50';
const bodyTrClass = const bodyTrClass =
'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-bg-blue-50 gl-hover-cursor-pointer gl-hover-border-b-solid gl-hover-border-blue-200'; 'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-bg-blue-50 gl-hover-cursor-pointer gl-hover-border-b-solid gl-hover-border-blue-200';
const TH_TEST_ID = { 'data-testid': 'alert-management-severity-sort' };
const initialPaginationState = { const initialPaginationState = {
currentPage: 1, currentPage: 1,
@ -55,12 +61,14 @@ export default {
"AlertManagement|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear.", "AlertManagement|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear.",
), ),
searchPlaceholder: __('Search or filter results...'), searchPlaceholder: __('Search or filter results...'),
unassigned: __('Unassigned'),
}, },
fields: [ fields: [
{ {
key: 'severity', key: 'severity',
label: s__('AlertManagement|Severity'), label: s__('AlertManagement|Severity'),
thClass: `${thClass} gl-w-eighth`, thClass: `${thClass} gl-w-eighth`,
thAttr: TH_TEST_ID,
tdClass: `${tdClass} rounded-top text-capitalize sortable-cell`, tdClass: `${tdClass} rounded-top text-capitalize sortable-cell`,
sortable: true, sortable: true,
}, },
@ -72,7 +80,7 @@ export default {
sortable: true, sortable: true,
}, },
{ {
key: 'title', key: 'alertLabel',
label: s__('AlertManagement|Alert'), label: s__('AlertManagement|Alert'),
thClass: `gl-pointer-events-none`, thClass: `gl-pointer-events-none`,
tdClass, tdClass,
@ -110,6 +118,9 @@ export default {
GlLoadingIcon, GlLoadingIcon,
GlTable, GlTable,
GlAlert, GlAlert,
GlAvatarsInline,
GlAvatarLink,
GlAvatar,
TimeAgo, TimeAgo,
GlIcon, GlIcon,
GlLink, GlLink,
@ -121,6 +132,9 @@ export default {
GlSprintf, GlSprintf,
AlertStatus, AlertStatus,
}, },
directives: {
GlTooltip: GlTooltipDirective,
},
props: { props: {
projectPath: { projectPath: {
type: String, type: String,
@ -264,11 +278,8 @@ export default {
const { category, action, label } = trackAlertStatusUpdateOptions; const { category, action, label } = trackAlertStatusUpdateOptions;
Tracking.event(category, action, { label, property: status }); Tracking.event(category, action, { label, property: status });
}, },
getAssignees(assignees) { hasAssignees(assignees) {
// TODO: Update to show list of assignee(s) after https://gitlab.com/gitlab-org/gitlab/-/issues/218405 return Boolean(assignees.nodes?.length);
return assignees.nodes?.length > 0
? assignees.nodes[0]?.username
: s__('AlertManagement|Unassigned');
}, },
getIssueLink(item) { getIssueLink(item) {
return joinPaths('/', this.projectPath, '-', 'issues', item.issueIid); return joinPaths('/', this.projectPath, '-', 'issues', item.issueIid);
@ -397,8 +408,14 @@ export default {
{{ item.eventCount }} {{ item.eventCount }}
</template> </template>
<template #cell(title)="{ item }"> <template #cell(alertLabel)="{ item }">
<div class="gl-max-w-full text-truncate" :title="item.title">{{ item.title }}</div> <div
class="gl-max-w-full text-truncate"
:title="`${item.iid} - ${item.title}`"
data-testid="idField"
>
#{{ item.iid }} {{ item.title }}
</div>
</template> </template>
<template #cell(issue)="{ item }"> <template #cell(issue)="{ item }">
@ -409,8 +426,32 @@ export default {
</template> </template>
<template #cell(assignees)="{ item }"> <template #cell(assignees)="{ item }">
<div class="gl-max-w-full text-truncate" data-testid="assigneesField"> <div data-testid="assigneesField">
{{ getAssignees(item.assignees) }} <template v-if="hasAssignees(item.assignees)">
<gl-avatars-inline
:avatars="item.assignees.nodes"
:collapsed="true"
:max-visible="4"
:avatar-size="24"
badge-tooltip-prop="name"
:badge-tooltip-max-chars="100"
>
<template #avatar="{ avatar }">
<gl-avatar-link
:key="avatar.username"
v-gl-tooltip
target="_blank"
:href="avatar.webUrl"
:title="avatar.name"
>
<gl-avatar :src="avatar.avatarUrl" :label="avatar.name" :size="24" />
</gl-avatar-link>
</template>
</gl-avatars-inline>
</template>
<template v-else>
{{ $options.i18n.unassigned }}
</template>
</div> </div>
</template> </template>

View file

@ -101,12 +101,12 @@ export default {
@keydown.esc.native="$emit('hide-dropdown')" @keydown.esc.native="$emit('hide-dropdown')"
@hide="$emit('hide-dropdown')" @hide="$emit('hide-dropdown')"
> >
<div v-if="isSidebar" class="dropdown-title text-center"> <div v-if="isSidebar" class="dropdown-title gl-display-flex">
<span class="alert-title">{{ s__('AlertManagement|Assign status') }}</span> <span class="alert-title gl-ml-auto">{{ s__('AlertManagement|Assign status') }}</span>
<gl-button <gl-button
:aria-label="__('Close')" :aria-label="__('Close')"
variant="link" variant="link"
class="dropdown-title-button dropdown-menu-close" class="dropdown-title-button dropdown-menu-close gl-ml-auto gl-text-black-normal!"
icon="close" icon="close"
@click="$emit('hide-dropdown')" @click="$emit('hide-dropdown')"
/> />

View file

@ -12,7 +12,7 @@ import {
} from '@gitlab/ui'; } from '@gitlab/ui';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { s__, __ } from '~/locale'; import { s__ } from '~/locale';
import alertSetAssignees from '../../graphql/mutations/alert_set_assignees.mutation.graphql'; import alertSetAssignees from '../../graphql/mutations/alert_set_assignees.mutation.graphql';
import SidebarAssignee from './sidebar_assignee.vue'; import SidebarAssignee from './sidebar_assignee.vue';
@ -82,8 +82,11 @@ export default {
userName() { userName() {
return this.alert?.assignees?.nodes[0]?.username; return this.alert?.assignees?.nodes[0]?.username;
}, },
assignedUser() { userFullName() {
return this.userName || __('None'); return this.alert?.assignees?.nodes[0]?.name;
},
userImg() {
return this.alert?.assignees?.nodes[0]?.avatarUrl;
}, },
sortedUsers() { sortedUsers() {
return this.users return this.users
@ -184,15 +187,15 @@ export default {
</script> </script>
<template> <template>
<div class="block alert-status"> <div class="block alert-assignees ">
<div ref="status" class="sidebar-collapsed-icon" @click="$emit('toggle-sidebar')"> <div ref="assignees" class="sidebar-collapsed-icon" @click="$emit('toggle-sidebar')">
<gl-icon name="user" :size="14" /> <gl-icon name="user" :size="14" />
<gl-loading-icon v-if="isUpdating" /> <gl-loading-icon v-if="isUpdating" />
</div> </div>
<gl-tooltip :target="() => $refs.status" boundary="viewport" placement="left"> <gl-tooltip :target="() => $refs.assignees" boundary="viewport" placement="left">
<gl-sprintf :message="$options.i18n.ASSIGNEES_BLOCK"> <gl-sprintf :message="$options.i18n.ASSIGNEES_BLOCK">
<template #assignees> <template #assignees>
{{ assignedUser }} {{ userName }}
</template> </template>
</gl-sprintf> </gl-sprintf>
</gl-tooltip> </gl-tooltip>
@ -215,19 +218,19 @@ export default {
<div class="dropdown dropdown-menu-selectable" :class="dropdownClass"> <div class="dropdown dropdown-menu-selectable" :class="dropdownClass">
<gl-deprecated-dropdown <gl-deprecated-dropdown
ref="dropdown" ref="dropdown"
:text="assignedUser" :text="userName"
class="w-100" class="w-100"
toggle-class="dropdown-menu-toggle" toggle-class="dropdown-menu-toggle"
variant="outline-default" variant="outline-default"
@keydown.esc.native="hideDropdown" @keydown.esc.native="hideDropdown"
@hide="hideDropdown" @hide="hideDropdown"
> >
<div class="dropdown-title"> <div class="dropdown-title gl-display-flex">
<span class="alert-title">{{ __('Assign To') }}</span> <span class="alert-title gl-ml-auto">{{ __('Assign To') }}</span>
<gl-button <gl-button
:aria-label="__('Close')" :aria-label="__('Close')"
variant="link" variant="link"
class="dropdown-title-button dropdown-menu-close" class="dropdown-title-button dropdown-menu-close gl-ml-auto gl-text-black-normal!"
icon="close" icon="close"
@click="hideDropdown" @click="hideDropdown"
/> />
@ -272,14 +275,28 @@ export default {
</div> </div>
<gl-loading-icon v-if="isUpdating" :inline="true" /> <gl-loading-icon v-if="isUpdating" :inline="true" />
<p v-else-if="!isDropdownShowing" class="value gl-m-0" :class="{ 'no-value': !userName }"> <div v-else-if="!isDropdownShowing" class="value gl-m-0" :class="{ 'no-value': !userName }">
<span v-if="userName" class="gl-text-gray-500" data-testid="assigned-users">{{ <div v-if="userName" class="gl-display-inline-flex gl-mt-2" data-testid="assigned-users">
assignedUser <span class="gl-relative mr-2">
}}</span> <img
<span v-else class="gl-display-flex gl-align-items-center"> :alt="userName"
:src="userImg"
:width="32"
class="avatar avatar-inline gl-m-0 s32"
data-qa-selector="avatar_image"
/>
</span>
<span class="gl-display-flex gl-flex-direction-column gl-overflow-hidden">
<strong class="dropdown-menu-user-full-name">
{{ userFullName }}
</strong>
<span class="dropdown-menu-user-username">{{ userName }}</span>
</span>
</div>
<span v-else class="gl-display-flex gl-align-items-center gl-line-height-normal">
{{ __('None') }} - {{ __('None') }} -
<gl-button <gl-button
class="gl-pl-2" class="gl-ml-2"
href="#" href="#"
variant="link" variant="link"
data-testid="unassigned-users" data-testid="unassigned-users"
@ -288,7 +305,7 @@ export default {
{{ __('assign yourself') }} {{ __('assign yourself') }}
</gl-button> </gl-button>
</span> </span>
</p> </div>
</div> </div>
</div> </div>
</template> </template>

View file

@ -1,8 +1,9 @@
<script> <script>
import produce from 'immer';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import Todo from '~/sidebar/components/todo_toggle/todo.vue'; import Todo from '~/sidebar/components/todo_toggle/todo.vue';
import createAlertTodo from '../../graphql/mutations/alert_todo_create.mutation.graphql'; import createAlertTodoMutation from '../../graphql/mutations/alert_todo_create.mutation.graphql';
import todoMarkDone from '../../graphql/mutations/alert_todo_mark_done.mutation.graphql'; import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.mutation.graphql';
import alertQuery from '../../graphql/queries/details.query.graphql'; import alertQuery from '../../graphql/queries/details.query.graphql';
export default { export default {
@ -52,7 +53,7 @@ export default {
}, },
methods: { methods: {
updateToDoCount(add) { updateToDoCount(add) {
const oldCount = parseInt(document.querySelector('.todos-count').innerText, 10); const oldCount = parseInt(document.querySelector('.js-todos-count').innerText, 10);
const count = add ? oldCount + 1 : oldCount - 1; const count = add ? oldCount + 1 : oldCount - 1;
const headerTodoEvent = new CustomEvent('todo:toggle', { const headerTodoEvent = new CustomEvent('todo:toggle', {
detail: { detail: {
@ -66,7 +67,7 @@ export default {
this.isUpdating = true; this.isUpdating = true;
return this.$apollo return this.$apollo
.mutate({ .mutate({
mutation: createAlertTodo, mutation: createAlertTodoMutation,
variables: { variables: {
iid: this.alert.iid, iid: this.alert.iid,
projectPath: this.projectPath, projectPath: this.projectPath,
@ -89,7 +90,7 @@ export default {
this.isUpdating = true; this.isUpdating = true;
return this.$apollo return this.$apollo
.mutate({ .mutate({
mutation: todoMarkDone, mutation: todoMarkDoneMutation,
variables: { variables: {
id: this.firstToDoId, id: this.firstToDoId,
}, },
@ -109,12 +110,15 @@ export default {
}); });
}, },
updateCache(store) { updateCache(store) {
const data = store.readQuery({ const sourceData = store.readQuery({
query: alertQuery, query: alertQuery,
variables: this.getAlertQueryVariables, variables: this.getAlertQueryVariables,
}); });
data.project.alertManagementAlerts.nodes[0].todos.nodes.shift(); const data = produce(sourceData, draftData => {
// eslint-disable-next-line no-param-reassign
draftData.project.alertManagementAlerts.nodes[0].todos.nodes = [];
});
store.writeQuery({ store.writeQuery({
query: alertQuery, query: alertQuery,

View file

@ -1,4 +1,5 @@
<script> <script>
/* eslint-disable vue/no-v-html */
import NoteHeader from '~/notes/components/note_header.vue'; import NoteHeader from '~/notes/components/note_header.vue';
import { spriteIcon } from '~/lib/utils/common_utils'; import { spriteIcon } from '~/lib/utils/common_utils';
@ -31,7 +32,7 @@ export default {
</script> </script>
<template> <template>
<li :id="noteAnchorId" class="timeline-entry note system-note note-wrapper"> <li :id="noteAnchorId" class="timeline-entry note system-note note-wrapper gl-px-0!">
<div class="timeline-entry-inner"> <div class="timeline-entry-inner">
<div class="timeline-icon" v-html="iconHtml"></div> <div class="timeline-icon" v-html="iconHtml"></div>
<div class="timeline-content"> <div class="timeline-content">

View file

@ -64,4 +64,4 @@ export const trackAlertStatusUpdateOptions = {
label: 'Status', label: 'Status',
}; };
export const DEFAULT_PAGE_SIZE = 10; export const DEFAULT_PAGE_SIZE = 20;

View file

@ -1,5 +1,6 @@
import Vue from 'vue'; import Vue from 'vue';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import produce from 'immer';
import { defaultDataIdFromObject } from 'apollo-cache-inmemory'; import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
import createDefaultClient from '~/lib/graphql'; import createDefaultClient from '~/lib/graphql';
import createRouter from './router'; import createRouter from './router';
@ -16,8 +17,11 @@ export default selector => {
const resolvers = { const resolvers = {
Mutation: { Mutation: {
toggleSidebarStatus: (_, __, { cache }) => { toggleSidebarStatus: (_, __, { cache }) => {
const data = cache.readQuery({ query: sidebarStatusQuery }); const sourceData = cache.readQuery({ query: sidebarStatusQuery });
data.sidebarStatus = !data.sidebarStatus; const data = produce(sourceData, draftData => {
// eslint-disable-next-line no-param-reassign
draftData.sidebarStatus = !draftData.sidebarStatus;
});
cache.writeQuery({ query: sidebarStatusQuery, data }); cache.writeQuery({ query: sidebarStatusQuery, data });
}, },
}, },
@ -34,6 +38,7 @@ export default selector => {
return defaultDataIdFromObject(object); return defaultDataIdFromObject(object);
}, },
}, },
assumeImmutableResults: true,
}), }),
}); });

View file

@ -8,7 +8,10 @@ fragment AlertListItem on AlertManagementAlert {
issueIid issueIid
assignees { assignees {
nodes { nodes {
name
username username
avatarUrl
webUrl
} }
} }
} }

View file

@ -10,6 +10,9 @@ mutation alertSetAssignees($projectPath: ID!, $assigneeUsernames: [String!]!, $i
assignees { assignees {
nodes { nodes {
username username
name
avatarUrl
webUrl
} }
} }
notes { notes {

View file

@ -20,6 +20,7 @@ const Api = {
projectPath: '/api/:version/projects/:id', projectPath: '/api/:version/projects/:id',
forkedProjectsPath: '/api/:version/projects/:id/forks', forkedProjectsPath: '/api/:version/projects/:id/forks',
projectLabelsPath: '/:namespace_path/:project_path/-/labels', projectLabelsPath: '/:namespace_path/:project_path/-/labels',
projectFileSchemaPath: '/:namespace_path/:project_path/-/schema/:ref/:filename',
projectUsersPath: '/api/:version/projects/:id/users', projectUsersPath: '/api/:version/projects/:id/users',
projectMergeRequestsPath: '/api/:version/projects/:id/merge_requests', projectMergeRequestsPath: '/api/:version/projects/:id/merge_requests',
projectMergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid', projectMergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid',
@ -42,7 +43,6 @@ const Api = {
userPostStatusPath: '/api/:version/user/status', userPostStatusPath: '/api/:version/user/status',
commitPath: '/api/:version/projects/:id/repository/commits/:sha', commitPath: '/api/:version/projects/:id/repository/commits/:sha',
commitsPath: '/api/:version/projects/:id/repository/commits', commitsPath: '/api/:version/projects/:id/repository/commits',
applySuggestionPath: '/api/:version/suggestions/:id/apply', applySuggestionPath: '/api/:version/suggestions/:id/apply',
applySuggestionBatchPath: '/api/:version/suggestions/batch_apply', applySuggestionBatchPath: '/api/:version/suggestions/batch_apply',
commitPipelinesPath: '/:project_id/commit/:sha/pipelines', commitPipelinesPath: '/:project_id/commit/:sha/pipelines',
@ -309,10 +309,12 @@ const Api = {
}); });
}, },
projectMilestones(id) { projectMilestones(id, params = {}) {
const url = Api.buildUrl(Api.projectMilestonesPath).replace(':id', encodeURIComponent(id)); const url = Api.buildUrl(Api.projectMilestonesPath).replace(':id', encodeURIComponent(id));
return axios.get(url); return axios.get(url, {
params,
});
}, },
mergeRequests(params = {}) { mergeRequests(params = {}) {

View file

@ -1,14 +1,23 @@
import $ from 'jquery'; import $ from 'jquery';
import initU2F from './u2f'; import initU2F from './u2f';
import initWebauthn from './webauthn';
import U2FRegister from './u2f/register'; import U2FRegister from './u2f/register';
import WebAuthnRegister from './webauthn/register';
export const mount2faAuthentication = () => { export const mount2faAuthentication = () => {
// Soon this will conditionally mount a webauthn app (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26692) if (gon.webauthn) {
initU2F(); initWebauthn();
} else {
initU2F();
}
}; };
export const mount2faRegistration = () => { export const mount2faRegistration = () => {
// Soon this will conditionally mount a webauthn app (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26692) if (gon.webauthn) {
const u2fRegister = new U2FRegister($('#js-register-u2f'), gon.u2f); const webauthnRegister = new WebAuthnRegister($('#js-register-token-2fa'), gon.webauthn);
u2fRegister.start(); webauthnRegister.start();
} else {
const u2fRegister = new U2FRegister($('#js-register-token-2fa'), gon.u2f);
u2fRegister.start();
}
}; };

View file

@ -40,7 +40,6 @@ export default class U2FAuthenticate {
this.signRequests = u2fParams.sign_requests.map(request => omit(request, 'challenge')); this.signRequests = u2fParams.sign_requests.map(request => omit(request, 'challenge'));
this.templates = { this.templates = {
setup: '#js-authenticate-token-2fa-setup',
inProgress: '#js-authenticate-token-2fa-in-progress', inProgress: '#js-authenticate-token-2fa-in-progress',
error: '#js-authenticate-token-2fa-error', error: '#js-authenticate-token-2fa-error',
authenticated: '#js-authenticate-token-2fa-authenticated', authenticated: '#js-authenticate-token-2fa-authenticated',
@ -86,7 +85,7 @@ export default class U2FAuthenticate {
renderError(error) { renderError(error) {
this.renderTemplate('error', { this.renderTemplate('error', {
error_message: error.message(), error_message: error.message(),
error_code: error.errorCode, error_name: error.errorCode,
}); });
return this.container.find('#js-token-2fa-try-again').on('click', this.renderInProgress); return this.container.find('#js-token-2fa-try-again').on('click', this.renderInProgress);
} }

View file

@ -1,5 +1,6 @@
import $ from 'jquery'; import $ from 'jquery';
import { template as lodashTemplate } from 'lodash'; import { template as lodashTemplate } from 'lodash';
import { __ } from '~/locale';
import importU2FLibrary from './util'; import importU2FLibrary from './util';
import U2FError from './error'; import U2FError from './error';
@ -24,11 +25,10 @@ export default class U2FRegister {
this.signRequests = u2fParams.sign_requests; this.signRequests = u2fParams.sign_requests;
this.templates = { this.templates = {
notSupported: '#js-register-u2f-not-supported', message: '#js-register-2fa-message',
setup: '#js-register-u2f-setup', setup: '#js-register-token-2fa-setup',
inProgress: '#js-register-u2f-in-progress', error: '#js-register-token-2fa-error',
error: '#js-register-u2f-error', registered: '#js-register-token-2fa-registered',
registered: '#js-register-u2f-registered',
}; };
} }
@ -65,18 +65,22 @@ export default class U2FRegister {
renderSetup() { renderSetup() {
this.renderTemplate('setup'); this.renderTemplate('setup');
return this.container.find('#js-setup-u2f-device').on('click', this.renderInProgress); return this.container.find('#js-setup-token-2fa-device').on('click', this.renderInProgress);
} }
renderInProgress() { renderInProgress() {
this.renderTemplate('inProgress'); this.renderTemplate('message', {
message: __(
'Trying to communicate with your device. Plug it in (if needed) and press the button on the device now.',
),
});
return this.register(); return this.register();
} }
renderError(error) { renderError(error) {
this.renderTemplate('error', { this.renderTemplate('error', {
error_message: error.message(), error_message: error.message(),
error_code: error.errorCode, error_name: error.errorCode,
}); });
return this.container.find('#js-token-2fa-try-again').on('click', this.renderSetup); return this.container.find('#js-token-2fa-try-again').on('click', this.renderSetup);
} }
@ -89,6 +93,10 @@ export default class U2FRegister {
} }
renderNotSupported() { renderNotSupported() {
return this.renderTemplate('notSupported'); return this.renderTemplate('message', {
message: __(
"Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer).",
),
});
} }
} }

View file

@ -0,0 +1,69 @@
import WebAuthnError from './error';
import WebAuthnFlow from './flow';
import { supported, convertGetParams, convertGetResponse } from './util';
// Authenticate WebAuthn devices for users to authenticate with.
//
// State Flow #1: setup -> in_progress -> authenticated -> POST to server
// State Flow #2: setup -> in_progress -> error -> setup
export default class WebAuthnAuthenticate {
constructor(container, form, webauthnParams, fallbackButton, fallbackUI) {
this.container = container;
this.webauthnParams = convertGetParams(JSON.parse(webauthnParams.options));
this.renderInProgress = this.renderInProgress.bind(this);
this.form = form;
this.fallbackButton = fallbackButton;
this.fallbackUI = fallbackUI;
if (this.fallbackButton) {
this.fallbackButton.addEventListener('click', this.switchToFallbackUI.bind(this));
}
this.flow = new WebAuthnFlow(container, {
inProgress: '#js-authenticate-token-2fa-in-progress',
error: '#js-authenticate-token-2fa-error',
authenticated: '#js-authenticate-token-2fa-authenticated',
});
this.container.on('click', '#js-token-2fa-try-again', this.renderInProgress);
}
start() {
if (!supported()) {
this.switchToFallbackUI();
} else {
this.renderInProgress();
}
}
authenticate() {
navigator.credentials
.get({ publicKey: this.webauthnParams })
.then(resp => {
const convertedResponse = convertGetResponse(resp);
this.renderAuthenticated(JSON.stringify(convertedResponse));
})
.catch(err => {
this.flow.renderError(new WebAuthnError(err, 'authenticate'));
});
}
renderInProgress() {
this.flow.renderTemplate('inProgress');
this.authenticate();
}
renderAuthenticated(deviceResponse) {
this.flow.renderTemplate('authenticated');
const container = this.container[0];
container.querySelector('#js-device-response').value = deviceResponse;
container.querySelector(this.form).submit();
this.fallbackButton.classList.add('hidden');
}
switchToFallbackUI() {
this.fallbackButton.classList.add('hidden');
this.container[0].classList.add('hidden');
this.fallbackUI.classList.remove('hidden');
}
}

View file

@ -0,0 +1,28 @@
import { __ } from '~/locale';
import { isHTTPS, FLOW_AUTHENTICATE, FLOW_REGISTER } from './util';
export default class WebAuthnError {
constructor(error, flowType) {
this.error = error;
this.errorName = error.name || 'UnknownError';
this.message = this.message.bind(this);
this.httpsDisabled = !isHTTPS();
this.flowType = flowType;
}
message() {
if (this.errorName === 'NotSupportedError') {
return __('Your device is not compatible with GitLab. Please try another device');
} else if (this.errorName === 'InvalidStateError' && this.flowType === FLOW_AUTHENTICATE) {
return __('This device has not been registered with us.');
} else if (this.errorName === 'InvalidStateError' && this.flowType === FLOW_REGISTER) {
return __('This device has already been registered with us.');
} else if (this.errorName === 'SecurityError' && this.httpsDisabled) {
return __(
'WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details.',
);
}
return __('There was a problem communicating with your device.');
}
}

View file

@ -0,0 +1,24 @@
import { template } from 'lodash';
/**
* Generic abstraction for WebAuthnFlows, especially for register / authenticate
*/
export default class WebAuthnFlow {
constructor(container, templates) {
this.container = container;
this.templates = templates;
}
renderTemplate(name, params) {
const templateString = document.querySelector(this.templates[name]).innerHTML;
const compiledTemplate = template(templateString);
this.container.html(compiledTemplate(params));
}
renderError(error) {
this.renderTemplate('error', {
error_message: error.message(),
error_name: error.errorName,
});
}
}

View file

@ -0,0 +1,13 @@
import $ from 'jquery';
import WebAuthnAuthenticate from './authenticate';
export default () => {
const webauthnAuthenticate = new WebAuthnAuthenticate(
$('#js-authenticate-token-2fa'),
'#js-login-token-2fa-form',
gon.webauthn,
document.querySelector('#js-login-2fa-device'),
document.querySelector('.js-2fa-form'),
);
webauthnAuthenticate.start();
};

View file

@ -0,0 +1,78 @@
import { __ } from '~/locale';
import WebAuthnError from './error';
import WebAuthnFlow from './flow';
import { supported, isHTTPS, convertCreateParams, convertCreateResponse } from './util';
// Register WebAuthn devices for users to authenticate with.
//
// State Flow #1: setup -> in_progress -> registered -> POST to server
// State Flow #2: setup -> in_progress -> error -> setup
export default class WebAuthnRegister {
constructor(container, webauthnParams) {
this.container = container;
this.renderInProgress = this.renderInProgress.bind(this);
this.webauthnOptions = convertCreateParams(webauthnParams.options);
this.flow = new WebAuthnFlow(container, {
message: '#js-register-2fa-message',
setup: '#js-register-token-2fa-setup',
error: '#js-register-token-2fa-error',
registered: '#js-register-token-2fa-registered',
});
this.container.on('click', '#js-token-2fa-try-again', this.renderInProgress);
}
start() {
if (!supported()) {
// we show a special error message when the user visits the site
// using a non-ssl connection as this makes WebAuthn unavailable in
// any case, regardless of the used browser
this.renderNotSupported(!isHTTPS());
} else {
this.renderSetup();
}
}
register() {
navigator.credentials
.create({
publicKey: this.webauthnOptions,
})
.then(cred => this.renderRegistered(JSON.stringify(convertCreateResponse(cred))))
.catch(err => this.flow.renderError(new WebAuthnError(err, 'register')));
}
renderSetup() {
this.flow.renderTemplate('setup');
this.container.find('#js-setup-token-2fa-device').on('click', this.renderInProgress);
}
renderInProgress() {
this.flow.renderTemplate('message', {
message: __(
'Trying to communicate with your device. Plug it in (if needed) and press the button on the device now.',
),
});
return this.register();
}
renderRegistered(deviceResponse) {
this.flow.renderTemplate('registered');
// Prefer to do this instead of interpolating using Underscore templates
// because of JSON escaping issues.
this.container.find('#js-device-response').val(deviceResponse);
}
renderNotSupported(noHttps) {
const message = noHttps
? __(
'WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details.',
)
: __(
"Your browser doesn't support WebAuthn. Please use a supported browser, e.g. Chrome (67+) or Firefox (60+).",
);
this.flow.renderTemplate('message', { message });
}
}

View file

@ -0,0 +1,120 @@
export function supported() {
return Boolean(
navigator.credentials &&
navigator.credentials.create &&
navigator.credentials.get &&
window.PublicKeyCredential,
);
}
export function isHTTPS() {
return window.location.protocol.startsWith('https');
}
export const FLOW_AUTHENTICATE = 'authenticate';
export const FLOW_REGISTER = 'register';
// adapted from https://stackoverflow.com/a/21797381/8204697
function base64ToBuffer(base64) {
const binaryString = window.atob(base64);
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i += 1) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}
// adapted from https://stackoverflow.com/a/9458996/8204697
function bufferToBase64(buffer) {
if (typeof buffer === 'string') {
return buffer;
}
let binary = '';
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i += 1) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
/**
* Returns a copy of the given object with the id property converted to buffer
*
* @param {Object} param
*/
function convertIdToBuffer({ id, ...rest }) {
return {
...rest,
id: base64ToBuffer(id),
};
}
/**
* Returns a copy of the given array with all `id`s of the items converted to buffer
*
* @param {Array} items
*/
function convertIdsToBuffer(items) {
return items.map(convertIdToBuffer);
}
/**
* Returns an object with keys of the given props, and values from the given object converted to base64
*
* @param {String} obj
* @param {Array} props
*/
function convertPropertiesToBase64(obj, props) {
return props.reduce(
(acc, property) => Object.assign(acc, { [property]: bufferToBase64(obj[property]) }),
{},
);
}
export function convertGetParams({ allowCredentials, challenge, ...rest }) {
return {
...rest,
...(allowCredentials ? { allowCredentials: convertIdsToBuffer(allowCredentials) } : {}),
challenge: base64ToBuffer(challenge),
};
}
export function convertGetResponse(webauthnResponse) {
return {
type: webauthnResponse.type,
id: webauthnResponse.id,
rawId: bufferToBase64(webauthnResponse.rawId),
response: convertPropertiesToBase64(webauthnResponse.response, [
'clientDataJSON',
'authenticatorData',
'signature',
'userHandle',
]),
clientExtensionResults: webauthnResponse.getClientExtensionResults(),
};
}
export function convertCreateParams({ challenge, user, excludeCredentials, ...rest }) {
return {
...rest,
challenge: base64ToBuffer(challenge),
user: convertIdToBuffer(user),
...(excludeCredentials ? { excludeCredentials: convertIdsToBuffer(excludeCredentials) } : {}),
};
}
export function convertCreateResponse(webauthnResponse) {
return {
type: webauthnResponse.type,
id: webauthnResponse.id,
rawId: bufferToBase64(webauthnResponse.rawId),
clientExtensionResults: webauthnResponse.getClientExtensionResults(),
response: convertPropertiesToBase64(webauthnResponse.response, [
'clientDataJSON',
'attestationObject',
]),
};
}

View file

@ -1,13 +1,12 @@
<script> <script>
import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui'; import { GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
export default { export default {
// name: 'Badge' is a false positive: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/25 // name: 'Badge' is a false positive: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/25
// eslint-disable-next-line @gitlab/require-i18n-strings // eslint-disable-next-line @gitlab/require-i18n-strings
name: 'Badge', name: 'Badge',
components: { components: {
Icon, GlIcon,
GlLoadingIcon, GlLoadingIcon,
}, },
directives: { directives: {
@ -84,7 +83,7 @@ export default {
<div v-show="hasError" class="btn-group"> <div v-show="hasError" class="btn-group">
<div class="btn btn-default btn-sm disabled"> <div class="btn btn-default btn-sm disabled">
<icon :size="16" class="gl-ml-3 gl-mr-3" name="doc-image" aria-hidden="true" /> <gl-icon :size="16" class="gl-ml-3 gl-mr-3" name="doc-image" aria-hidden="true" />
</div> </div>
<div class="btn btn-default btn-sm disabled"> <div class="btn btn-default btn-sm disabled">
<span class="gl-ml-3 gl-mr-3">{{ s__('Badges|No badge image') }}</span> <span class="gl-ml-3 gl-mr-3">{{ s__('Badges|No badge image') }}</span>
@ -99,7 +98,7 @@ export default {
type="button" type="button"
@click="reloadImage" @click="reloadImage"
> >
<icon :size="16" name="retry" /> <gl-icon :size="16" name="retry" />
</button> </button>
</div> </div>
</template> </template>

View file

@ -1,10 +1,10 @@
<script> <script>
/* eslint-disable vue/no-v-html */
import { escape, debounce } from 'lodash'; import { escape, debounce } from 'lodash';
import { mapActions, mapState } from 'vuex'; import { mapActions, mapState } from 'vuex';
import { GlLoadingIcon, GlFormInput, GlFormGroup } from '@gitlab/ui'; import { GlLoadingIcon, GlFormInput, GlFormGroup, GlButton } from '@gitlab/ui';
import { deprecatedCreateFlash as createFlash } from '~/flash'; import { deprecatedCreateFlash as createFlash } from '~/flash';
import { s__, sprintf } from '~/locale'; import { s__, sprintf } from '~/locale';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import createEmptyBadge from '../empty_badge'; import createEmptyBadge from '../empty_badge';
import Badge from './badge.vue'; import Badge from './badge.vue';
@ -14,7 +14,7 @@ export default {
name: 'BadgeForm', name: 'BadgeForm',
components: { components: {
Badge, Badge,
LoadingButton, GlButton,
GlLoadingIcon, GlLoadingIcon,
GlFormInput, GlFormInput,
GlFormGroup, GlFormGroup,
@ -219,23 +219,23 @@ export default {
</div> </div>
<div v-if="isEditing" class="row-content-block gl-display-flex gl-justify-content-end"> <div v-if="isEditing" class="row-content-block gl-display-flex gl-justify-content-end">
<button class="btn btn-cancel gl-mr-4" type="button" @click="onCancel"> <gl-button class="btn-cancel gl-mr-4" data-testid="cancelEditing" @click="onCancel">
{{ __('Cancel') }} {{ __('Cancel') }}
</button> </gl-button>
<loading-button <gl-button
:loading="isSaving" :loading="isSaving"
:label="s__('Badges|Save changes')"
type="submit" type="submit"
container-class="btn btn-success" variant="success"
/> category="primary"
data-testid="saveEditing"
>
{{ s__('Badges|Save changes') }}
</gl-button>
</div> </div>
<div v-else class="gl-display-flex gl-justify-content-end form-group"> <div v-else class="gl-display-flex gl-justify-content-end form-group">
<loading-button <gl-button :loading="isSaving" type="submit" variant="success" category="primary">
:loading="isSaving" {{ s__('Badges|Add badge') }}
:label="s__('Badges|Add badge')" </gl-button>
type="submit"
container-class="btn btn-success"
/>
</div> </div>
</form> </form>
</template> </template>

View file

@ -1,8 +1,7 @@
<script> <script>
import { mapActions, mapState } from 'vuex'; import { mapActions, mapState } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui'; import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import { PROJECT_BADGE } from '../constants'; import { PROJECT_BADGE } from '../constants';
import Badge from './badge.vue'; import Badge from './badge.vue';
@ -10,7 +9,7 @@ export default {
name: 'BadgeListRow', name: 'BadgeListRow',
components: { components: {
Badge, Badge,
Icon, GlIcon,
GlLoadingIcon, GlLoadingIcon,
}, },
props: { props: {
@ -58,7 +57,7 @@ export default {
type="button" type="button"
@click="editBadge(badge)" @click="editBadge(badge)"
> >
<icon :size="16" :aria-label="__('Edit')" name="pencil" /> <gl-icon :size="16" :aria-label="__('Edit')" name="pencil" />
</button> </button>
<button <button
:disabled="badge.isDeleting" :disabled="badge.isDeleting"
@ -68,7 +67,7 @@ export default {
data-target="#delete-badge-modal" data-target="#delete-badge-modal"
@click="updateBadgeInModal(badge)" @click="updateBadgeInModal(badge)"
> >
<icon :size="16" :aria-label="__('Delete')" name="remove" /> <gl-icon :size="16" :aria-label="__('Delete')" name="remove" />
</button> </button>
<gl-loading-icon v-show="badge.isDeleting" :inline="true" /> <gl-loading-icon v-show="badge.isDeleting" :inline="true" />
</div> </div>

View file

@ -1,4 +1,5 @@
<script> <script>
/* eslint-disable vue/no-v-html */
import { mapActions, mapGetters, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import { GlButton } from '@gitlab/ui'; import { GlButton } from '@gitlab/ui';
import NoteableNote from '~/notes/components/noteable_note.vue'; import NoteableNote from '~/notes/components/noteable_note.vue';

View file

@ -1,16 +1,16 @@
<script> <script>
import { mapActions, mapGetters, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui'; import { GlButton, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { sprintf, n__ } from '~/locale'; import { sprintf, n__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import DraftsCount from './drafts_count.vue'; import DraftsCount from './drafts_count.vue';
import PublishButton from './publish_button.vue'; import PublishButton from './publish_button.vue';
import PreviewItem from './preview_item.vue'; import PreviewItem from './preview_item.vue';
export default { export default {
components: { components: {
GlButton,
GlLoadingIcon, GlLoadingIcon,
Icon, GlIcon,
DraftsCount, DraftsCount,
PublishButton, PublishButton,
PreviewItem, PreviewItem,
@ -29,7 +29,7 @@ export default {
watch: { watch: {
showPreviewDropdown() { showPreviewDropdown() {
if (this.showPreviewDropdown && this.$refs.dropdown) { if (this.showPreviewDropdown && this.$refs.dropdown) {
this.$nextTick(() => this.$refs.dropdown.focus()); this.$nextTick(() => this.$refs.dropdown.$el.focus());
} }
}, },
}, },
@ -63,32 +63,35 @@ export default {
show: showPreviewDropdown, show: showPreviewDropdown,
}" }"
> >
<button <gl-button
ref="dropdown" ref="dropdown"
type="button" type="button"
class="btn btn-success review-preview-dropdown-toggle qa-review-preview-toggle" category="primary"
variant="success"
class="review-preview-dropdown-toggle qa-review-preview-toggle"
@click="toggleReviewDropdown" @click="toggleReviewDropdown"
> >
{{ __('Finish review') }} {{ __('Finish review') }}
<drafts-count /> <drafts-count />
<icon name="angle-up" /> <gl-icon name="angle-up" />
</button> </gl-button>
<div <div
class="dropdown-menu dropdown-menu-large dropdown-menu-right dropdown-open-top" class="dropdown-menu dropdown-menu-large dropdown-menu-right dropdown-open-top"
:class="{ :class="{
show: showPreviewDropdown, show: showPreviewDropdown,
}" }"
> >
<div class="dropdown-title"> <div class="dropdown-title gl-display-flex gl-align-items-center">
{{ dropdownTitle }} <span class="gl-ml-auto">{{ dropdownTitle }}</span>
<button <gl-button
:aria-label="__('Close')" :aria-label="__('Close')"
type="button" type="button"
class="dropdown-title-button dropdown-menu-close" category="tertiary"
size="small"
class="dropdown-title-button gl-ml-auto gl-p-0!"
icon="close"
@click="toggleReviewDropdown" @click="toggleReviewDropdown"
> />
<icon name="close" />
</button>
</div> </div>
<div class="dropdown-content"> <div class="dropdown-content">
<ul v-if="isNotesFetched"> <ul v-if="isNotesFetched">

View file

@ -1,9 +1,8 @@
<script> <script>
import { mapActions, mapGetters } from 'vuex'; import { mapActions, mapGetters } from 'vuex';
import { GlSprintf } from '@gitlab/ui'; import { GlSprintf, GlIcon } from '@gitlab/ui';
import { IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants'; import { IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants';
import { sprintf, __ } from '~/locale'; import { sprintf, __ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import resolvedStatusMixin from '../mixins/resolved_status'; import resolvedStatusMixin from '../mixins/resolved_status';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { import {
@ -14,7 +13,7 @@ import {
export default { export default {
components: { components: {
Icon, GlIcon,
GlSprintf, GlSprintf,
}, },
mixins: [resolvedStatusMixin, glFeatureFlagsMixin()], mixins: [resolvedStatusMixin, glFeatureFlagsMixin()],
@ -101,7 +100,7 @@ export default {
@click="scrollToDraft(draft)" @click="scrollToDraft(draft)"
> >
<span class="review-preview-item-header"> <span class="review-preview-item-header">
<icon class="flex-shrink-0" :name="iconName" /> <gl-icon class="flex-shrink-0" :name="iconName" />
<span <span
class="bold text-nowrap" class="bold text-nowrap"
:class="{ 'gl-align-items-center': glFeatures.multilineComments }" :class="{ 'gl-align-items-center': glFeatures.multilineComments }"
@ -138,7 +137,7 @@ export default {
v-if="draft.discussion_id && resolvedStatusMessage" v-if="draft.discussion_id && resolvedStatusMessage"
class="review-preview-item-footer draft-note-resolution p-0" class="review-preview-item-footer draft-note-resolution p-0"
> >
<icon class="gl-mr-3" name="status_success" /> {{ resolvedStatusMessage }} <gl-icon class="gl-mr-3" name="status_success" /> {{ resolvedStatusMessage }}
</span> </span>
</button> </button>
</template> </template>

View file

@ -1,4 +1,5 @@
<script> <script>
/* eslint-disable vue/no-v-html */
import { mapActions, mapState, mapGetters } from 'vuex'; import { mapActions, mapState, mapGetters } from 'vuex';
import { GlModal, GlModalDirective, GlButton } from '@gitlab/ui'; import { GlModal, GlModalDirective, GlButton } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale'; import { sprintf, s__ } from '~/locale';

View file

@ -3,7 +3,6 @@ import { mapActions } from 'vuex';
import store from '~/mr_notes/stores'; import store from '~/mr_notes/stores';
import ReviewBar from './components/review_bar.vue'; import ReviewBar from './components/review_bar.vue';
// eslint-disable-next-line import/prefer-default-export
export const initReviewBar = () => { export const initReviewBar = () => {
const el = document.getElementById('js-review-bar'); const el = document.getElementById('js-review-bar');

View file

@ -1,8 +1,13 @@
import Autosize from 'autosize'; import Autosize from 'autosize';
import { waitForCSSLoaded } from '../helpers/startup_css_helper';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const autosizeEls = document.querySelectorAll('.js-autosize'); waitForCSSLoaded(() => {
const autosizeEls = document.querySelectorAll('.js-autosize');
Autosize(autosizeEls); Autosize(autosizeEls);
Autosize.update(autosizeEls); Autosize.update(autosizeEls);
autosizeEls.forEach(el => el.classList.add('js-autosize-initialized'));
});
}); });

View file

@ -1,7 +1,7 @@
import $ from 'jquery';
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';
@ -15,9 +15,27 @@ import initCollapseSidebarOnWindowResize from './collapse_sidebar_on_window_resi
import initSelect2Dropdowns from './select2'; import initSelect2Dropdowns from './select2';
installGlEmojiElement(); installGlEmojiElement();
initGFMInput();
initCopyAsGFM(); initCopyAsGFM();
initCopyToClipboard(); initCopyToClipboard();
initPageShortcuts(); initPageShortcuts();
initCollapseSidebarOnWindowResize(); initCollapseSidebarOnWindowResize();
initSelect2Dropdowns(); initSelect2Dropdowns();
document.addEventListener('DOMContentLoaded', () => {
window.requestIdleCallback(
() => {
// Check if we have to Load GFM Input
const $gfmInputs = $('.js-gfm-input:not(.js-gfm-input-initialized)');
if ($gfmInputs.length) {
import(/* webpackChunkName: 'initGFMInput' */ './markdown/gfm_auto_complete')
.then(({ default: initGFMInput }) => {
initGFMInput($gfmInputs);
})
.catch(() => {});
}
},
{ timeout: 500 },
);
});

View file

@ -2,8 +2,8 @@ import $ from 'jquery';
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete'; import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
import { parseBoolean } from '~/lib/utils/common_utils'; import { parseBoolean } from '~/lib/utils/common_utils';
export default function initGFMInput() { export default function initGFMInput($els) {
$('.js-gfm-input:not(.js-vue-textarea)').each((i, el) => { $els.each((i, el) => {
const gfm = new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources); const gfm = new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources);
const enableGFM = parseBoolean(el.dataset.supportsAutocomplete); const enableGFM = parseBoolean(el.dataset.supportsAutocomplete);
@ -14,6 +14,7 @@ export default function initGFMInput() {
milestones: enableGFM, milestones: enableGFM,
mergeRequests: enableGFM, mergeRequests: enableGFM,
labels: enableGFM, labels: enableGFM,
vulnerabilities: enableGFM,
}); });
}); });
} }

View file

@ -5,7 +5,6 @@ import renderMermaid from './render_mermaid';
import renderMetrics from './render_metrics'; import renderMetrics from './render_metrics';
import highlightCurrentUser from './highlight_current_user'; import highlightCurrentUser from './highlight_current_user';
import initUserPopovers from '../../user_popovers'; import initUserPopovers from '../../user_popovers';
import initMRPopovers from '../../mr_popover';
// Render GitLab flavoured Markdown // Render GitLab flavoured Markdown
// //
@ -17,9 +16,25 @@ $.fn.renderGFM = function renderGFM() {
renderMermaid(this.find('.js-render-mermaid')); renderMermaid(this.find('.js-render-mermaid'));
highlightCurrentUser(this.find('.gfm-project_member').get()); highlightCurrentUser(this.find('.gfm-project_member').get());
initUserPopovers(this.find('.js-user-link').get()); initUserPopovers(this.find('.js-user-link').get());
initMRPopovers(this.find('.gfm-merge_request').get());
const mrPopoverElements = this.find('.gfm-merge_request').get();
if (mrPopoverElements.length) {
import(/* webpackChunkName: 'MrPopoverBundle' */ '../../mr_popover')
.then(({ default: initMRPopovers }) => {
initMRPopovers(mrPopoverElements);
})
.catch(() => {});
}
renderMetrics(this.find('.js-render-metrics').get()); renderMetrics(this.find('.js-render-metrics').get());
return this; return this;
}; };
$(() => $('body').renderGFM()); $(() => {
window.requestIdleCallback(
() => {
$('body').renderGFM();
},
{ timeout: 500 },
);
});

View file

@ -1,5 +1,6 @@
import { deprecatedCreateFlash as flash } from '~/flash'; import { deprecatedCreateFlash as flash } from '~/flash';
import { s__, sprintf } from '~/locale'; import { s__, sprintf } from '~/locale';
import { differenceInMilliseconds } from '~/lib/utils/datetime_utility';
// Renders math using KaTeX in any element with the // Renders math using KaTeX in any element with the
// `js-render-math` class // `js-render-math` class
@ -111,7 +112,7 @@ class SafeMathRenderer {
// Give the browser time to reflow the svg // Give the browser time to reflow the svg
waitForReflow(() => { waitForReflow(() => {
const deltaTime = Date.now() - this.startTime; const deltaTime = differenceInMilliseconds(this.startTime);
this.totalMS += deltaTime; this.totalMS += deltaTime;
this.renderElement(); this.renderElement();

View file

@ -1,5 +1,3 @@
import Shortcuts from './shortcuts/shortcuts';
export default function initPageShortcuts() { export default function initPageShortcuts() {
const { page } = document.body.dataset; const { page } = document.body.dataset;
const pagesWithCustomShortcuts = [ const pagesWithCustomShortcuts = [
@ -29,7 +27,9 @@ export default function initPageShortcuts() {
// the pages above have their own shortcuts sub-classes instantiated elsewhere // the pages above have their own shortcuts sub-classes instantiated elsewhere
// TODO: replace this whitelist with something more automated/maintainable // TODO: replace this whitelist with something more automated/maintainable
if (page && !pagesWithCustomShortcuts.includes(page)) { if (page && !pagesWithCustomShortcuts.includes(page)) {
return new Shortcuts(); import(/* webpackChunkName: 'shortcutsBundle' */ './shortcuts/shortcuts')
.then(({ default: Shortcuts }) => new Shortcuts())
.catch(() => {});
} }
return false; return false;
} }

View file

@ -2,6 +2,7 @@ import $ from 'jquery';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import Mousetrap from 'mousetrap'; import Mousetrap from 'mousetrap';
import Vue from 'vue'; import Vue from 'vue';
import { flatten } from 'lodash';
import { disableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle'; import { disableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle';
import ShortcutsToggle from './shortcuts_toggle.vue'; import ShortcutsToggle from './shortcuts_toggle.vue';
import axios from '../../lib/utils/axios_utils'; import axios from '../../lib/utils/axios_utils';
@ -9,13 +10,13 @@ import { refreshCurrentPage, visitUrl } from '../../lib/utils/url_utility';
import findAndFollowLink from '../../lib/utils/navigation_utility'; import findAndFollowLink from '../../lib/utils/navigation_utility';
import { parseBoolean, getCspNonceValue } from '~/lib/utils/common_utils'; import { parseBoolean, getCspNonceValue } from '~/lib/utils/common_utils';
const defaultStopCallback = Mousetrap.stopCallback; const defaultStopCallback = Mousetrap.prototype.stopCallback;
Mousetrap.stopCallback = (e, element, combo) => { Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) {
if (['ctrl+shift+p', 'command+shift+p'].indexOf(combo) !== -1) { if (['ctrl+shift+p', 'command+shift+p'].indexOf(combo) !== -1) {
return false; return false;
} }
return defaultStopCallback(e, element, combo); return defaultStopCallback.call(this, e, element, combo);
}; };
function initToggleButton() { function initToggleButton() {
@ -27,6 +28,39 @@ function initToggleButton() {
}); });
} }
/**
* The key used to save and fetch the local Mousetrap instance
* attached to a `<textarea>` element using `jQuery.data`
*/
const LOCAL_MOUSETRAP_DATA_KEY = 'local-mousetrap-instance';
/**
* Gets a mapping of toolbar button => keyboard shortcuts
* associated to the given markdown editor `<textarea>` element
*
* @param {HTMLTextAreaElement} $textarea The jQuery-wrapped `<textarea>`
* element to extract keyboard shortcuts from
*
* @returns A Map with keys that are jQuery-wrapped toolbar buttons
* (i.e. `$toolbarBtn`) and values that are arrays of string
* keyboard shortcuts (e.g. `['command+k', 'ctrl+k]`).
*/
function getToolbarBtnToShortcutsMap($textarea) {
const $allToolbarBtns = $textarea.closest('.md-area').find('.js-md');
const map = new Map();
$allToolbarBtns.each(function attachToolbarBtnHandler() {
const $toolbarBtn = $(this);
const keyboardShortcuts = $toolbarBtn.data('md-shortcuts');
if (keyboardShortcuts?.length) {
map.set($toolbarBtn, keyboardShortcuts);
}
});
return map;
}
export default class Shortcuts { export default class Shortcuts {
constructor() { constructor() {
this.onToggleHelp = this.onToggleHelp.bind(this); this.onToggleHelp = this.onToggleHelp.bind(this);
@ -34,6 +68,7 @@ export default class Shortcuts {
Mousetrap.bind('?', this.onToggleHelp); Mousetrap.bind('?', this.onToggleHelp);
Mousetrap.bind('s', Shortcuts.focusSearch); Mousetrap.bind('s', Shortcuts.focusSearch);
Mousetrap.bind('/', Shortcuts.focusSearch);
Mousetrap.bind('f', this.focusFilter.bind(this)); Mousetrap.bind('f', this.focusFilter.bind(this));
Mousetrap.bind('p b', Shortcuts.onTogglePerfBar); Mousetrap.bind('p b', Shortcuts.onTogglePerfBar);
@ -143,4 +178,62 @@ export default class Shortcuts {
e.preventDefault(); e.preventDefault();
} }
} }
/**
* Initializes markdown editor shortcuts on the provided `<textarea>` element
*
* @param {JQuery} $textarea The jQuery-wrapped `<textarea>` element
* where markdown shortcuts should be enabled
* @param {Function} handler The handler to call when a
* keyboard shortcut is pressed inside the markdown `<textarea>`
*/
static initMarkdownEditorShortcuts($textarea, handler) {
const toolbarBtnToShortcutsMap = getToolbarBtnToShortcutsMap($textarea);
const localMousetrap = new Mousetrap($textarea[0]);
// Save a reference to the local mousetrap instance on the <textarea>
// so that it can be retrieved when unbinding shortcut handlers
$textarea.data(LOCAL_MOUSETRAP_DATA_KEY, localMousetrap);
toolbarBtnToShortcutsMap.forEach((keyboardShortcuts, $toolbarBtn) => {
localMousetrap.bind(keyboardShortcuts, e => {
e.preventDefault();
handler($toolbarBtn);
});
});
// Get an array of all shortcut strings that have been added above
const allShortcuts = flatten([...toolbarBtnToShortcutsMap.values()]);
const originalStopCallback = Mousetrap.prototype.stopCallback;
localMousetrap.stopCallback = function newStopCallback(e, element, combo) {
if (allShortcuts.includes(combo)) {
return false;
}
return originalStopCallback.call(this, e, element, combo);
};
}
/**
* Removes markdown editor shortcut handlers originally attached
* with `initMarkdownEditorShortcuts`.
*
* Note: it is safe to call this function even if `initMarkdownEditorShortcuts`
* has _not_ yet been called on the given `<textarea>`.
*
* @param {JQuery} $textarea The jQuery-wrapped `<textarea>`
* to remove shortcut handlers from
*/
static removeMarkdownEditorShortcuts($textarea) {
const localMousetrap = $textarea.data(LOCAL_MOUSETRAP_DATA_KEY);
if (localMousetrap) {
getToolbarBtnToShortcutsMap($textarea).forEach(keyboardShortcuts => {
localMousetrap.unbind(keyboardShortcuts);
});
}
}
} }

View file

@ -5,12 +5,11 @@ export default class ShortcutsFindFile extends ShortcutsNavigation {
constructor(projectFindFile) { constructor(projectFindFile) {
super(); super();
const oldStopCallback = Mousetrap.stopCallback; const oldStopCallback = Mousetrap.prototype.stopCallback;
this.projectFindFile = projectFindFile;
Mousetrap.stopCallback = (e, element, combo) => { Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) {
if ( if (
element === this.projectFindFile.inputElement[0] && element === projectFindFile.inputElement[0] &&
(combo === 'up' || combo === 'down' || combo === 'esc' || combo === 'enter') (combo === 'up' || combo === 'down' || combo === 'esc' || combo === 'enter')
) { ) {
// when press up/down key in textbox, cursor prevent to move to home/end // when press up/down key in textbox, cursor prevent to move to home/end
@ -18,12 +17,12 @@ export default class ShortcutsFindFile extends ShortcutsNavigation {
return false; return false;
} }
return oldStopCallback(e, element, combo); return oldStopCallback.call(this, e, element, combo);
}; };
Mousetrap.bind('up', this.projectFindFile.selectRowUp); Mousetrap.bind('up', projectFindFile.selectRowUp);
Mousetrap.bind('down', this.projectFindFile.selectRowDown); Mousetrap.bind('down', projectFindFile.selectRowDown);
Mousetrap.bind('esc', this.projectFindFile.goToTree); Mousetrap.bind('esc', projectFindFile.goToTree);
Mousetrap.bind('enter', this.projectFindFile.goToBlob); Mousetrap.bind('enter', projectFindFile.goToBlob);
} }
} }

View file

@ -46,7 +46,7 @@ export default {
blobGlobalId: this.fileGlobalId, blobGlobalId: this.fileGlobalId,
}); });
this.editor.onChangeContent(debounce(this.onFileChange.bind(this), 250)); this.editor.onDidChangeModelContent(debounce(this.onFileChange.bind(this), 250));
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
if (!performance.getEntriesByName(SNIPPET_MARK_BLOBS_CONTENT).length) { if (!performance.getEntriesByName(SNIPPET_MARK_BLOBS_CONTENT).length) {

View file

@ -1,41 +0,0 @@
<script>
import { GlFormInputGroup, GlDeprecatedButton, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
export default {
components: {
GlFormInputGroup,
GlDeprecatedButton,
GlIcon,
},
props: {
url: {
type: String,
required: true,
},
},
data() {
return {
optionValues: [
// eslint-disable-next-line no-useless-escape
{ name: __('Embed'), value: `<script src='${this.url}.js'><\/script>` },
{ name: __('Share'), value: this.url },
],
};
},
};
</script>
<template>
<gl-form-input-group
id="embeddable-text"
:predefined-options="optionValues"
readonly
select-on-click
>
<template #append>
<gl-deprecated-button new-style data-clipboard-target="#embeddable-text">
<gl-icon name="copy-to-clipboard" :title="__('Copy')" />
</gl-deprecated-button>
</template>
</gl-form-input-group>
</template>

View file

@ -1,16 +1,18 @@
import $ from 'jquery'; import $ from 'jquery';
import Api from '~/api'; import Api from '~/api';
import toast from '~/vue_shared/plugins/global_toast';
import { __ } from '~/locale';
import initPopover from '~/blob/suggest_gitlab_ci_yml';
import { deprecatedCreateFlash as Flash } from '../flash'; import { deprecatedCreateFlash as Flash } from '../flash';
import FileTemplateTypeSelector from './template_selectors/type_selector'; import FileTemplateTypeSelector from './template_selectors/type_selector';
import BlobCiYamlSelector from './template_selectors/ci_yaml_selector'; import BlobCiYamlSelector from './template_selectors/ci_yaml_selector';
import DockerfileSelector from './template_selectors/dockerfile_selector'; import DockerfileSelector from './template_selectors/dockerfile_selector';
import GitignoreSelector from './template_selectors/gitignore_selector'; import GitignoreSelector from './template_selectors/gitignore_selector';
import LicenseSelector from './template_selectors/license_selector'; import LicenseSelector from './template_selectors/license_selector';
import MetricsDashboardSelector from './template_selectors/metrics_dashboard_selector'; import MetricsDashboardSelector from './template_selectors/metrics_dashboard_selector';
import toast from '~/vue_shared/plugins/global_toast';
import { __ } from '~/locale';
import initPopover from '~/blob/suggest_gitlab_ci_yml';
export default class FileTemplateMediator { export default class FileTemplateMediator {
constructor({ editor, currentAction, projectId }) { constructor({ editor, currentAction, projectId }) {

View file

@ -45,11 +45,15 @@ export default class FileTemplateSelector {
} }
renderLoading() { renderLoading() {
this.$loadingIcon.addClass('fa-spinner fa-spin').removeClass('fa-chevron-down'); this.$loadingIcon
.addClass('gl-spinner gl-spinner-orange gl-spinner-sm')
.removeClass('fa-chevron-down');
} }
renderLoaded() { renderLoaded() {
this.$loadingIcon.addClass('fa-chevron-down').removeClass('fa-spinner fa-spin'); this.$loadingIcon
.addClass('fa-chevron-down')
.removeClass('gl-spinner gl-spinner-orange gl-spinner-sm');
} }
reportSelection(options) { reportSelection(options) {

View file

@ -1,5 +1,5 @@
<script> <script>
import { GlModal, GlSprintf, GlLink } from '@gitlab/ui'; import { GlModal, GlSprintf, GlLink, GlButton } from '@gitlab/ui';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import { sprintf, s__, __ } from '~/locale'; import { sprintf, s__, __ } from '~/locale';
import { glEmojiTag } from '~/emoji'; import { glEmojiTag } from '~/emoji';
@ -18,6 +18,8 @@ export default {
helpMessage: s__( helpMessage: s__(
`MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more.`, `MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more.`,
), ),
pipelinesButton: s__('MR widget|See your pipeline in action'),
mergeRequestButton: s__('MR widget|Back to the Merge request'),
modalTitle: sprintf( modalTitle: sprintf(
__("That's it, well done!%{celebrate}"), __("That's it, well done!%{celebrate}"),
{ {
@ -25,11 +27,13 @@ export default {
}, },
false, false,
), ),
goToTrackValue: 10, goToTrackValuePipelines: 10,
goToTrackValueMergeRequest: 20,
trackEvent: 'click_button', trackEvent: 'click_button',
components: { components: {
GlModal, GlModal,
GlSprintf, GlSprintf,
GlButton,
GlLink, GlLink,
}, },
mixins: [trackingMixin], mixins: [trackingMixin],
@ -38,6 +42,11 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
projectMergeRequestsPath: {
type: String,
required: false,
default: '',
},
commitCookie: { commitCookie: {
type: String, type: String,
required: true, required: true,
@ -59,6 +68,15 @@ export default {
property: this.humanAccess, property: this.humanAccess,
}; };
}, },
goToMergeRequestPath() {
return this.commitCookiePath || this.projectMergeRequestsPath;
},
commitCookiePath() {
const cookieVal = Cookies.get(this.commitCookie);
if (cookieVal !== 'true') return cookieVal;
return '';
},
}, },
mounted() { mounted() {
this.track(); this.track();
@ -100,17 +118,28 @@ export default {
</template> </template>
</gl-sprintf> </gl-sprintf>
<template #modal-footer> <template #modal-footer>
<a <gl-button
ref="goto" v-if="projectMergeRequestsPath"
:href="goToPipelinesPath" ref="goToMergeRequest"
class="btn btn-success" :href="goToMergeRequestPath"
:data-track-property="humanAccess" :data-track-property="humanAccess"
:data-track-value="$options.goToTrackValue" :data-track-value="$options.goToTrackValueMergeRequest"
:data-track-event="$options.trackEvent" :data-track-event="$options.trackEvent"
:data-track-label="trackLabel" :data-track-label="trackLabel"
> >
{{ __('See your pipeline in action') }} {{ $options.mergeRequestButton }}
</a> </gl-button>
<gl-button
ref="goToPipelines"
:href="goToPipelinesPath"
variant="success"
:data-track-property="humanAccess"
:data-track-value="$options.goToTrackValuePipelines"
:data-track-event="$options.trackEvent"
:data-track-label="trackLabel"
>
{{ $options.pipelinesButton }}
</gl-button>
</template> </template>
</gl-modal> </gl-modal>
</template> </template>

View file

@ -49,6 +49,10 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
mergeRequestPath: {
type: String,
required: true,
},
}, },
data() { data() {
return { return {
@ -109,7 +113,7 @@ export default {
:css-classes="['suggest-gitlab-ci-yml', 'ml-4']" :css-classes="['suggest-gitlab-ci-yml', 'ml-4']"
> >
<template #title> <template #title>
<span v-html="suggestTitle"></span> <span>{{ suggestTitle }}</span>
<span class="ml-auto"> <span class="ml-auto">
<gl-button <gl-button
:aria-label="__('Close')" :aria-label="__('Close')"

View file

@ -10,6 +10,7 @@ export default el =>
target: el.dataset.target, target: el.dataset.target,
trackLabel: el.dataset.trackLabel, trackLabel: el.dataset.trackLabel,
dismissKey: el.dataset.dismissKey, dismissKey: el.dataset.dismissKey,
mergeRequestPath: el.dataset.mergeRequestPath,
humanAccess: el.dataset.humanAccess, humanAccess: el.dataset.humanAccess,
}, },
}); });

View file

@ -0,0 +1,50 @@
<script>
import { GlAlert, GlButton } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
export default {
components: {
GlAlert,
GlButton,
},
props: {
dismissEndpoint: {
type: String,
required: true,
},
featureId: {
type: String,
required: true,
},
editPath: {
type: String,
required: true,
},
},
data() {
return {
showAlert: true,
};
},
methods: {
dismissAlert() {
this.showAlert = false;
return axios.post(this.dismissEndpoint, {
feature_name: this.featureId,
});
},
},
};
</script>
<template>
<gl-alert v-if="showAlert" class="gl-mt-5" @dismiss="dismissAlert">
{{ __('The Web IDE offers advanced syntax highlighting capabilities and more.') }}
<div class="gl-mt-5">
<gl-button :href="editPath" category="primary" variant="info">{{
__('Open Web IDE')
}}</gl-button>
</div>
</gl-alert>
</template>

View file

@ -0,0 +1,20 @@
import Vue from 'vue';
import WebIdeAlert from './components/web_ide_alert.vue';
export default el => {
const { dismissEndpoint, featureId, editPath } = el.dataset;
// eslint-disable-next-line no-new
new Vue({
el,
render(createElement) {
return createElement(WebIdeAlert, {
props: {
dismissEndpoint,
featureId,
editPath,
},
});
},
});
};

View file

@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */ /* eslint-disable class-methods-use-this */
import $ from 'jquery'; import $ from 'jquery';
import '~/gl_dropdown'; import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class TemplateSelector { export default class TemplateSelector {
constructor({ dropdown, data, pattern, wrapper, editor, $input } = {}) { constructor({ dropdown, data, pattern, wrapper, editor, $input } = {}) {
@ -19,7 +19,7 @@ export default class TemplateSelector {
} }
initDropdown(dropdown, data) { initDropdown(dropdown, data) {
return $(dropdown).glDropdown({ return initDeprecatedJQueryDropdown($(dropdown), {
data, data,
filterable: true, filterable: true,
selectable: true, selectable: true,

View file

@ -1,4 +1,5 @@
import FileTemplateSelector from '../file_template_selector'; import FileTemplateSelector from '../file_template_selector';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class BlobCiYamlSelector extends FileTemplateSelector { export default class BlobCiYamlSelector extends FileTemplateSelector {
constructor({ mediator }) { constructor({ mediator }) {
@ -15,7 +16,7 @@ export default class BlobCiYamlSelector extends FileTemplateSelector {
initDropdown() { initDropdown() {
// maybe move to super class as well // maybe move to super class as well
this.$dropdown.glDropdown({ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.$dropdown.data('data'), data: this.$dropdown.data('data'),
filterable: true, filterable: true,
selectable: true, selectable: true,

View file

@ -1,5 +1,6 @@
import FileTemplateSelector from '../file_template_selector'; import FileTemplateSelector from '../file_template_selector';
import { __ } from '~/locale'; import { __ } from '~/locale';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class DockerfileSelector extends FileTemplateSelector { export default class DockerfileSelector extends FileTemplateSelector {
constructor({ mediator }) { constructor({ mediator }) {
@ -16,7 +17,7 @@ export default class DockerfileSelector extends FileTemplateSelector {
initDropdown() { initDropdown() {
// maybe move to super class as well // maybe move to super class as well
this.$dropdown.glDropdown({ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.$dropdown.data('data'), data: this.$dropdown.data('data'),
filterable: true, filterable: true,
selectable: true, selectable: true,

View file

@ -1,4 +1,5 @@
import FileTemplateSelector from '../file_template_selector'; import FileTemplateSelector from '../file_template_selector';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class BlobGitignoreSelector extends FileTemplateSelector { export default class BlobGitignoreSelector extends FileTemplateSelector {
constructor({ mediator }) { constructor({ mediator }) {
@ -14,7 +15,7 @@ export default class BlobGitignoreSelector extends FileTemplateSelector {
} }
initDropdown() { initDropdown() {
this.$dropdown.glDropdown({ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.$dropdown.data('data'), data: this.$dropdown.data('data'),
filterable: true, filterable: true,
selectable: true, selectable: true,

View file

@ -1,4 +1,5 @@
import FileTemplateSelector from '../file_template_selector'; import FileTemplateSelector from '../file_template_selector';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class BlobLicenseSelector extends FileTemplateSelector { export default class BlobLicenseSelector extends FileTemplateSelector {
constructor({ mediator }) { constructor({ mediator }) {
@ -14,7 +15,7 @@ export default class BlobLicenseSelector extends FileTemplateSelector {
} }
initDropdown() { initDropdown() {
this.$dropdown.glDropdown({ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.$dropdown.data('data'), data: this.$dropdown.data('data'),
filterable: true, filterable: true,
selectable: true, selectable: true,

View file

@ -1,4 +1,5 @@
import FileTemplateSelector from '../file_template_selector'; import FileTemplateSelector from '../file_template_selector';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class MetricsDashboardSelector extends FileTemplateSelector { export default class MetricsDashboardSelector extends FileTemplateSelector {
constructor({ mediator }) { constructor({ mediator }) {
@ -14,7 +15,7 @@ export default class MetricsDashboardSelector extends FileTemplateSelector {
} }
initDropdown() { initDropdown() {
this.$dropdown.glDropdown({ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.$dropdown.data('data'), data: this.$dropdown.data('data'),
filterable: true, filterable: true,
selectable: true, selectable: true,

View file

@ -1,4 +1,5 @@
import FileTemplateSelector from '../file_template_selector'; import FileTemplateSelector from '../file_template_selector';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class FileTemplateTypeSelector extends FileTemplateSelector { export default class FileTemplateTypeSelector extends FileTemplateSelector {
constructor({ mediator, dropdownData }) { constructor({ mediator, dropdownData }) {
@ -12,7 +13,7 @@ export default class FileTemplateTypeSelector extends FileTemplateSelector {
} }
initDropdown() { initDropdown() {
this.$dropdown.glDropdown({ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.config.dropdownData, data: this.config.dropdownData,
filterable: false, filterable: false,
selectable: true, selectable: true,

View file

@ -1,20 +1,16 @@
import Editor from '~/editor/editor_lite'; import Editor from '~/editor/editor_lite';
export function initEditorLite({ el, ...args }) { export function initEditorLite({ el, ...args }) {
if (!el) {
throw new Error(`"el" parameter is required to initialize Editor`);
}
const editor = new Editor({ const editor = new Editor({
scrollbar: { scrollbar: {
alwaysConsumeMouseWheel: false, alwaysConsumeMouseWheel: false,
}, },
}); });
editor.createInstance({
return editor.createInstance({
el, el,
...args, ...args,
}); });
return editor;
} }
export default () => ({}); export default () => ({});

View file

@ -7,12 +7,14 @@ import BlobFileDropzone from '../blob/blob_file_dropzone';
import initPopover from '~/blob/suggest_gitlab_ci_yml'; import initPopover from '~/blob/suggest_gitlab_ci_yml';
import { disableButtonIfEmptyField, setCookie } from '~/lib/utils/common_utils'; import { disableButtonIfEmptyField, setCookie } from '~/lib/utils/common_utils';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import initWebIdeAlert from '~/blob/suggest_web_ide_ci';
export default () => { export default () => {
const editBlobForm = $('.js-edit-blob-form'); const editBlobForm = $('.js-edit-blob-form');
const uploadBlobForm = $('.js-upload-blob-form'); const uploadBlobForm = $('.js-upload-blob-form');
const deleteBlobForm = $('.js-delete-blob-form'); const deleteBlobForm = $('.js-delete-blob-form');
const suggestEl = document.querySelector('.js-suggest-gitlab-ci-yml'); const suggestEl = document.querySelector('.js-suggest-gitlab-ci-yml');
const alertEl = document.getElementById('js-suggest-web-ide-ci');
if (editBlobForm.length) { if (editBlobForm.length) {
const urlRoot = editBlobForm.data('relativeUrlRoot'); const urlRoot = editBlobForm.data('relativeUrlRoot');
@ -65,12 +67,15 @@ export default () => {
if (commitButton) { if (commitButton) {
const { dismissKey, humanAccess } = suggestEl.dataset; const { dismissKey, humanAccess } = suggestEl.dataset;
const urlParams = new URLSearchParams(window.location.search);
const mergeRequestPath = urlParams.get('mr_path') || true;
const commitCookieName = `suggest_gitlab_ci_yml_commit_${dismissKey}`; const commitCookieName = `suggest_gitlab_ci_yml_commit_${dismissKey}`;
const commitTrackLabel = 'suggest_gitlab_ci_yml_commit_changes'; const commitTrackLabel = 'suggest_gitlab_ci_yml_commit_changes';
const commitTrackValue = '20'; const commitTrackValue = '20';
commitButton.addEventListener('click', () => { commitButton.addEventListener('click', () => {
setCookie(commitCookieName, true); setCookie(commitCookieName, mergeRequestPath);
Tracking.event(undefined, 'click_button', { Tracking.event(undefined, 'click_button', {
label: commitTrackLabel, label: commitTrackLabel,
@ -80,4 +85,8 @@ export default () => {
}); });
} }
} }
if (alertEl) {
initWebIdeAlert(alertEl);
}
}; };

View file

@ -40,9 +40,10 @@ export default class EditBlob {
const MarkdownExtensionPromise = this.options.isMarkdown const MarkdownExtensionPromise = this.options.isMarkdown
? import('~/editor/editor_markdown_ext') ? import('~/editor/editor_markdown_ext')
: Promise.resolve(false); : Promise.resolve(false);
const FileTemplateExtensionPromise = import('~/editor/editor_file_template_ext');
return Promise.all([EditorPromise, MarkdownExtensionPromise]) return Promise.all([EditorPromise, MarkdownExtensionPromise, FileTemplateExtensionPromise])
.then(([EditorModule, MarkdownExtension]) => { .then(([EditorModule, MarkdownExtension, FileTemplateExtension]) => {
const EditorLite = EditorModule.default; const EditorLite = EditorModule.default;
const editorEl = document.getElementById('editor'); const editorEl = document.getElementById('editor');
const fileNameEl = const fileNameEl =
@ -50,18 +51,16 @@ export default class EditBlob {
const fileContentEl = document.getElementById('file-content'); const fileContentEl = document.getElementById('file-content');
const form = document.querySelector('.js-edit-blob-form'); const form = document.querySelector('.js-edit-blob-form');
this.editor = new EditorLite(); const rootEditor = new EditorLite();
if (MarkdownExtension) { this.editor = rootEditor.createInstance({
this.editor.use(MarkdownExtension.default);
}
this.editor.createInstance({
el: editorEl, el: editorEl,
blobPath: fileNameEl.value, blobPath: fileNameEl.value,
blobContent: editorEl.innerText, blobContent: editorEl.innerText,
}); });
rootEditor.use([MarkdownExtension.default, FileTemplateExtension.default], this.editor);
fileNameEl.addEventListener('change', () => { fileNameEl.addEventListener('change', () => {
this.editor.updateModelLanguage(fileNameEl.value); this.editor.updateModelLanguage(fileNameEl.value);
}); });

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